Explorar o código

LibGL: Implement state for all pixel store parameters

This implements the state and context parameters for all packing and
unpacking parameters accepted by `glPixelStore*`.
Jelle Raaijmakers %!s(int64=2) %!d(string=hai) anos
pai
achega
fe5419da0f

+ 24 - 32
Userland/Libraries/LibGL/ContextParameter.cpp

@@ -89,19 +89,21 @@ Optional<ContextParameter> GLContext::get_context_parameter(GLenum name)
     case GL_NORMALIZE:
         return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_normalize } };
     case GL_PACK_ALIGNMENT:
-        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_pack_alignment } };
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.pack_alignment } };
     case GL_PACK_IMAGE_HEIGHT:
-        return ContextParameter { .type = GL_BOOL, .value = { .integer_value = 0 } };
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.image_height } };
     case GL_PACK_LSB_FIRST:
-        return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
+        return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_packing_parameters.least_significant_bit_first } };
     case GL_PACK_ROW_LENGTH:
-        return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.row_length } };
+    case GL_PACK_SKIP_IMAGES:
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.skip_images } };
     case GL_PACK_SKIP_PIXELS:
-        return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.skip_pixels } };
     case GL_PACK_SKIP_ROWS:
-        return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.skip_rows } };
     case GL_PACK_SWAP_BYTES:
-        return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
+        return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_packing_parameters.swap_bytes } };
     case GL_POINT_SMOOTH:
         return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_point_smooth } };
     case GL_POINT_SIZE:
@@ -154,19 +156,21 @@ Optional<ContextParameter> GLContext::get_context_parameter(GLenum name)
         return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = generation_enabled } };
     }
     case GL_UNPACK_ALIGNMENT:
-        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpack_alignment } };
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.pack_alignment } };
     case GL_UNPACK_IMAGE_HEIGHT:
-        return ContextParameter { .type = GL_BOOL, .value = { .integer_value = 0 } };
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.image_height } };
     case GL_UNPACK_LSB_FIRST:
-        return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
+        return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_unpacking_parameters.least_significant_bit_first } };
     case GL_UNPACK_ROW_LENGTH:
-        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpack_row_length } };
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.row_length } };
+    case GL_UNPACK_SKIP_IMAGES:
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.skip_images } };
     case GL_UNPACK_SKIP_PIXELS:
-        return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.skip_pixels } };
     case GL_UNPACK_SKIP_ROWS:
-        return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
+        return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.skip_rows } };
     case GL_UNPACK_SWAP_BYTES:
-        return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
+        return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_unpacking_parameters.swap_bytes } };
     case GL_VIEWPORT:
         return ContextParameter {
             .type = GL_INT,
@@ -616,25 +620,13 @@ GLboolean GLContext::gl_is_enabled(GLenum capability)
 
 GPU::PackingSpecification GLContext::get_packing_specification(PackingType packing_type)
 {
-    // Make use of the fact that the GL_PACK_* and GL_UNPACK_* enum constants are in the exact same order
-    auto const offset = (packing_type == PackingType::Unpack) ? 0 : (GL_PACK_SWAP_BYTES - GL_UNPACK_SWAP_BYTES);
-    auto get_packing_value = [&](GLenum packing_parameter) -> GLint {
-        GLint value;
-        gl_get_integerv(packing_parameter + offset, &value);
-        return value;
-    };
-
-    // FIXME: add support for GL_UNPACK_SKIP_PIXELS, GL_UNPACK_SKIP_ROWS and GL_UNPACK_LSB_FIRST
-    GLint byte_alignment { get_packing_value(GL_UNPACK_ALIGNMENT) };
-    GLint swap_bytes { get_packing_value(GL_UNPACK_SWAP_BYTES) };
-    GLint depth_stride { get_packing_value(GL_UNPACK_IMAGE_HEIGHT) };
-    GLint row_stride { get_packing_value(GL_UNPACK_ROW_LENGTH) };
-
+    // FIXME: add support for .least_significant_bit_first, .skip_images, .skip_pixels and .skip_rows
+    auto const& pixel_parameters = (packing_type == PackingType::Pack) ? m_packing_parameters : m_unpacking_parameters;
     return {
-        .depth_stride = static_cast<u32>(depth_stride),
-        .row_stride = static_cast<u32>(row_stride),
-        .byte_alignment = static_cast<u8>(byte_alignment),
-        .component_bytes_order = swap_bytes == GL_TRUE ? GPU::ComponentBytesOrder::Reversed : GPU::ComponentBytesOrder::Normal,
+        .depth_stride = static_cast<u32>(pixel_parameters.image_height),
+        .row_stride = static_cast<u32>(pixel_parameters.row_length),
+        .byte_alignment = pixel_parameters.pack_alignment,
+        .component_bytes_order = pixel_parameters.swap_bytes ? GPU::ComponentBytesOrder::Reversed : GPU::ComponentBytesOrder::Normal,
     };
 }
 

+ 36 - 6
Userland/Libraries/LibGL/GLContext.cpp

@@ -773,19 +773,49 @@ void GLContext::gl_fogi(GLenum pname, GLint param)
 
 void GLContext::gl_pixel_storei(GLenum pname, GLint param)
 {
-    // FIXME: Implement missing parameters
+    auto const is_packing_parameter = (pname >= GL_PACK_SWAP_BYTES && pname <= GL_PACK_ALIGNMENT)
+        || pname == GL_PACK_SKIP_IMAGES
+        || pname == GL_PACK_IMAGE_HEIGHT;
+    auto& pixel_parameters = is_packing_parameter ? m_packing_parameters : m_unpacking_parameters;
+
     switch (pname) {
     case GL_PACK_ALIGNMENT:
+    case GL_UNPACK_ALIGNMENT:
         RETURN_WITH_ERROR_IF(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE);
-        m_pack_alignment = param;
+        pixel_parameters.pack_alignment = param;
+        break;
+    case GL_PACK_IMAGE_HEIGHT:
+    case GL_UNPACK_IMAGE_HEIGHT:
+        RETURN_WITH_ERROR_IF(param < 0, GL_INVALID_VALUE);
+        pixel_parameters.image_height = param;
         break;
+    case GL_PACK_LSB_FIRST:
+    case GL_UNPACK_LSB_FIRST:
+        pixel_parameters.least_significant_bit_first = (param != 0);
+        break;
+    case GL_PACK_ROW_LENGTH:
     case GL_UNPACK_ROW_LENGTH:
         RETURN_WITH_ERROR_IF(param < 0, GL_INVALID_VALUE);
-        m_unpack_row_length = static_cast<size_t>(param);
+        pixel_parameters.row_length = param;
         break;
-    case GL_UNPACK_ALIGNMENT:
-        RETURN_WITH_ERROR_IF(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE);
-        m_unpack_alignment = param;
+    case GL_PACK_SKIP_IMAGES:
+    case GL_UNPACK_SKIP_IMAGES:
+        RETURN_WITH_ERROR_IF(param < 0, GL_INVALID_VALUE);
+        pixel_parameters.skip_images = param;
+        break;
+    case GL_PACK_SKIP_PIXELS:
+    case GL_UNPACK_SKIP_PIXELS:
+        RETURN_WITH_ERROR_IF(param < 0, GL_INVALID_VALUE);
+        pixel_parameters.skip_pixels = param;
+        break;
+    case GL_PACK_SKIP_ROWS:
+    case GL_UNPACK_SKIP_ROWS:
+        RETURN_WITH_ERROR_IF(param < 0, GL_INVALID_VALUE);
+        pixel_parameters.skip_rows = param;
+        break;
+    case GL_PACK_SWAP_BYTES:
+    case GL_UNPACK_SWAP_BYTES:
+        pixel_parameters.swap_bytes = (param != 0);
         break;
     default:
         RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);

+ 12 - 3
Userland/Libraries/LibGL/GLContext.h

@@ -510,9 +510,18 @@ private:
     Vector<VertexAttribPointer> m_client_tex_coord_pointer;
     VertexAttribPointer m_client_normal_pointer;
 
-    u8 m_pack_alignment { 4 };
-    GLsizei m_unpack_row_length { 0 };
-    u8 m_unpack_alignment { 4 };
+    struct PixelParameters {
+        i32 image_height { 0 };
+        bool least_significant_bit_first { false };
+        u8 pack_alignment { 4 };
+        i32 row_length { 0 };
+        i32 skip_images { 0 };
+        i32 skip_pixels { 0 };
+        i32 skip_rows { 0 };
+        bool swap_bytes { false };
+    };
+    PixelParameters m_packing_parameters;
+    PixelParameters m_unpacking_parameters;
 
     // Point drawing configuration
     bool m_point_smooth { false };