summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Unverwerth <s.unverwerth@serenityos.org>2021-12-22 22:00:08 +0100
committerBrian Gianforcaro <b.gianfo@gmail.com>2021-12-24 05:10:28 -0800
commit39545d4b4958464d1e4d119fd72da2a62aa2fffb (patch)
treeca66a0dcb688132f90c1f69e54616b492a6b18dc
parent908a6339ecc97f8d259ecfafe076d6010502244f (diff)
downloadserenity-39545d4b4958464d1e4d119fd72da2a62aa2fffb.zip
LibGL: Attach device image to texture object and upload image data
-rw-r--r--Userland/Libraries/LibGL/SoftwareGLContext.cpp23
-rw-r--r--Userland/Libraries/LibGL/Tex/Texture.h7
-rw-r--r--Userland/Libraries/LibGL/Tex/Texture2D.cpp33
3 files changed, 63 insertions, 0 deletions
diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.cpp b/Userland/Libraries/LibGL/SoftwareGLContext.cpp
index 54e56f04b7..7d9a99bc63 100644
--- a/Userland/Libraries/LibGL/SoftwareGLContext.cpp
+++ b/Userland/Libraries/LibGL/SoftwareGLContext.cpp
@@ -764,6 +764,29 @@ void SoftwareGLContext::gl_tex_image_2d(GLenum target, GLint level, GLint intern
RETURN_WITH_ERROR_IF((height & (height - 1)) != 0, GL_INVALID_VALUE);
RETURN_WITH_ERROR_IF(border < 0 || border > 1, GL_INVALID_VALUE);
+ if (level == 0) {
+ // FIXME: OpenGL has the concept of texture and mipmap completeness. A texture has to fulfill certain criteria to be considered complete.
+ // Trying to render while an incomplete texture is bound will result in an error.
+ // Here we simply create a complete device image when mipmap level 0 is attached to the texture object. This has the unfortunate side effect
+ // that constructing GL textures in any but the default mipmap order, going from level 0 upwards will cause mip levels to stay uninitialized.
+ // To be spec compliant we should create the device image once the texture has become complete and is used for rendering the first time.
+ // All images that were attached before the device image was created need to be stored somewhere to be used to initialize the device image once complete.
+ SoftGPU::ImageFormat device_format;
+ switch (internal_format) {
+ case GL_RGB:
+ device_format = SoftGPU::ImageFormat::RGB888;
+ break;
+
+ case GL_RGBA:
+ device_format = SoftGPU::ImageFormat::RGBA8888;
+ break;
+
+ default:
+ VERIFY_NOT_REACHED();
+ }
+ m_active_texture_unit->bound_texture_2d()->set_device_image(m_rasterizer.create_image(device_format, width, height, 1, 999, 1));
+ }
+
m_active_texture_unit->bound_texture_2d()->upload_texture_data(level, internal_format, width, height, border, format, type, data, m_unpack_row_length, m_unpack_alignment);
}
diff --git a/Userland/Libraries/LibGL/Tex/Texture.h b/Userland/Libraries/LibGL/Tex/Texture.h
index d3f9ddfc2a..89dfe00196 100644
--- a/Userland/Libraries/LibGL/Tex/Texture.h
+++ b/Userland/Libraries/LibGL/Tex/Texture.h
@@ -7,6 +7,7 @@
#pragma once
#include <AK/RefCounted.h>
+#include <LibSoftGPU/Image.h>
namespace GL {
@@ -18,6 +19,12 @@ public:
virtual bool is_texture_2d() const { return false; }
virtual bool is_texture_3d() const { return false; }
virtual bool is_cube_map() const { return false; }
+
+ RefPtr<SoftGPU::Image> device_image() { return m_device_image; }
+ void set_device_image(RefPtr<SoftGPU::Image> image) { m_device_image = image; }
+
+private:
+ RefPtr<SoftGPU::Image> m_device_image;
};
}
diff --git a/Userland/Libraries/LibGL/Tex/Texture2D.cpp b/Userland/Libraries/LibGL/Tex/Texture2D.cpp
index 7608b74ecb..d6a04f4d42 100644
--- a/Userland/Libraries/LibGL/Tex/Texture2D.cpp
+++ b/Userland/Libraries/LibGL/Tex/Texture2D.cpp
@@ -106,6 +106,39 @@ void Texture2D::replace_sub_texture_data(GLuint lod, GLint xoffset, GLint yoffse
pixel_byte_array += row_remainder_bytes;
}
+
+ if (!device_image().is_null()) {
+ SoftGPU::ImageDataLayout layout;
+ layout.column_stride = pixel_size_bytes;
+ layout.row_stride = physical_width_bytes + (byte_alignment - physical_width_bytes % byte_alignment) % byte_alignment;
+ layout.depth_stride = 0;
+ if (type == GL_UNSIGNED_SHORT_5_6_5) {
+ layout.format = SoftGPU::ImageFormat::RGB565;
+ } else if (type == GL_UNSIGNED_BYTE) {
+ if (format == GL_RGB)
+ layout.format = SoftGPU::ImageFormat::RGB888;
+ else if (format == GL_BGR)
+ layout.format = SoftGPU::ImageFormat::BGR888;
+ else if (format == GL_RGBA)
+ layout.format = SoftGPU::ImageFormat::RGBA8888;
+ else if (format == GL_BGRA)
+ layout.format = SoftGPU::ImageFormat::BGRA8888;
+ }
+
+ Vector3<unsigned> offset {
+ static_cast<unsigned>(xoffset),
+ static_cast<unsigned>(yoffset),
+ 0
+ };
+
+ Vector3<unsigned> size {
+ static_cast<unsigned>(width),
+ static_cast<unsigned>(height),
+ 1
+ };
+
+ device_image()->write_texels(0, lod, offset, size, pixels, layout);
+ }
}
}