diff options
-rw-r--r-- | Userland/Libraries/LibGL/SoftwareGLContext.cpp | 23 | ||||
-rw-r--r-- | Userland/Libraries/LibGL/Tex/Texture.h | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibGL/Tex/Texture2D.cpp | 33 |
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); + } } } |