浏览代码

LibGL: Implement glPixelStorei

This sets the length of a row for the image to be transferred. This
value is measured in pixels. When a rectangle with a width less than
this value is transferred the remaining pixels of this row are skipped.
Stephan Unverwerth 3 年之前
父节点
当前提交
19a08ff187

+ 1 - 0
Userland/Libraries/LibGL/GL/gl.h

@@ -377,6 +377,7 @@ GLAPI void glPolygonMode(GLenum face, GLenum mode);
 GLAPI void glFogfv(GLenum mode, GLfloat* params);
 GLAPI void glFogf(GLenum pname, GLfloat param);
 GLAPI void glFogi(GLenum pname, GLint param);
+GLAPI void glPixelStorei(GLenum pname, GLint param);
 
 #ifdef __cplusplus
 }

+ 1 - 0
Userland/Libraries/LibGL/GLContext.h

@@ -80,6 +80,7 @@ public:
     virtual void gl_fogfv(GLenum pname, GLfloat* params) = 0;
     virtual void gl_fogf(GLenum pname, GLfloat params) = 0;
     virtual void gl_fogi(GLenum pname, GLint param) = 0;
+    virtual void gl_pixel_store(GLenum pname, GLfloat param) = 0;
 
     virtual void present() = 0;
 };

+ 5 - 0
Userland/Libraries/LibGL/GLUtils.cpp

@@ -134,3 +134,8 @@ void glPolygonMode(GLenum face, GLenum mode)
 {
     g_gl_context->gl_polygon_mode(face, mode);
 }
+
+void glPixelStorei(GLenum pname, GLint param)
+{
+    g_gl_context->gl_pixel_store(pname, param);
+}

+ 15 - 1
Userland/Libraries/LibGL/SoftwareGLContext.cpp

@@ -650,7 +650,7 @@ void SoftwareGLContext::gl_tex_image_2d(GLenum target, GLint level, GLint intern
     RETURN_WITH_ERROR_IF((width & 2) != 0 || (height & 2) != 0, GL_INVALID_VALUE);
     RETURN_WITH_ERROR_IF(border < 0 || border > 1, GL_INVALID_VALUE);
 
-    m_active_texture_unit->bound_texture_2d()->upload_texture_data(target, level, internal_format, width, height, border, format, type, data);
+    m_active_texture_unit->bound_texture_2d()->upload_texture_data(target, level, internal_format, width, height, border, format, type, data, m_unpack_row_length);
 }
 
 void SoftwareGLContext::gl_tex_parameter(GLenum target, GLenum pname, GLfloat param)
@@ -1805,6 +1805,20 @@ void SoftwareGLContext::gl_fogi(GLenum pname, GLint param)
     m_rasterizer.set_options(options);
 }
 
+void SoftwareGLContext::gl_pixel_store(GLenum pname, GLfloat param)
+{
+    // FIXME: Implement missing parameters
+    switch (pname) {
+    case GL_UNPACK_ROW_LENGTH:
+        RETURN_WITH_ERROR_IF(param < 0, GL_INVALID_VALUE);
+        m_unpack_row_length = static_cast<size_t>(param);
+        break;
+    default:
+        RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
+        break;
+    }
+}
+
 void SoftwareGLContext::present()
 {
     m_rasterizer.blit_to(*m_frontbuffer);

+ 3 - 0
Userland/Libraries/LibGL/SoftwareGLContext.h

@@ -90,6 +90,7 @@ public:
     virtual void gl_fogfv(GLenum pname, GLfloat* params) override;
     virtual void gl_fogf(GLenum pname, GLfloat param) override;
     virtual void gl_fogi(GLenum pname, GLint param) override;
+    virtual void gl_pixel_store(GLenum pname, GLfloat param) override;
     virtual void present() override;
 
 private:
@@ -254,6 +255,8 @@ private:
     VertexAttribPointer m_client_vertex_pointer;
     VertexAttribPointer m_client_color_pointer;
     VertexAttribPointer m_client_tex_coord_pointer;
+
+    size_t m_unpack_row_length { 0 };
 };
 
 }

+ 57 - 33
Userland/Libraries/LibGL/Tex/Texture2D.cpp

@@ -12,7 +12,7 @@
 
 namespace GL {
 
-void Texture2D::upload_texture_data(GLenum, GLint lod, GLint internal_format, GLsizei width, GLsizei height, GLint, GLenum format, GLenum, const GLvoid* pixels)
+void Texture2D::upload_texture_data(GLenum, GLint lod, GLint internal_format, GLsizei width, GLsizei height, GLint, GLenum format, GLenum, const GLvoid* pixels, size_t pixels_per_row)
 {
     // NOTE: Some target, format, and internal formats are currently unsupported.
     // Considering we control this library, and `gl.h` itself, we don't need to add any
@@ -34,44 +34,68 @@ void Texture2D::upload_texture_data(GLenum, GLint lod, GLint internal_format, GL
 
     mip.pixel_data().clear();
     if (format == GL_RGBA) {
-        for (auto i = 0; i < width * height * 4; i += 4) {
-            u32 r = pixel_byte_array[i + 0];
-            u32 g = pixel_byte_array[i + 1];
-            u32 b = pixel_byte_array[i + 2];
-            u32 a = pixel_byte_array[i + 3];
-
-            u32 pixel = ((a << 24) | (r << 16) | (g << 8) | b);
-            mip.pixel_data().append(pixel);
+        for (auto y = 0; y < height; y++) {
+            for (auto x = 0; x < width; x++) {
+                u32 r = *pixel_byte_array++;
+                u32 g = *pixel_byte_array++;
+                u32 b = *pixel_byte_array++;
+                u32 a = *pixel_byte_array++;
+
+                u32 pixel = ((a << 24) | (r << 16) | (g << 8) | b);
+                mip.pixel_data().append(pixel);
+            }
+
+            if (pixels_per_row > 0) {
+                pixel_byte_array += (pixels_per_row - width) * 4;
+            }
         }
     } else if (format == GL_BGRA) {
-        for (auto i = 0; i < width * height * 4; i += 4) {
-            u32 b = pixel_byte_array[i + 0];
-            u32 g = pixel_byte_array[i + 1];
-            u32 r = pixel_byte_array[i + 2];
-            u32 a = pixel_byte_array[i + 3];
-
-            u32 pixel = ((a << 24) | (r << 16) | (g << 8) | b);
-            mip.pixel_data().append(pixel);
+        for (auto y = 0; y < height; y++) {
+            for (auto x = 0; x < width; x++) {
+                u32 b = *pixel_byte_array++;
+                u32 g = *pixel_byte_array++;
+                u32 r = *pixel_byte_array++;
+                u32 a = *pixel_byte_array++;
+
+                u32 pixel = ((a << 24) | (r << 16) | (g << 8) | b);
+                mip.pixel_data().append(pixel);
+            }
+
+            if (pixels_per_row > 0) {
+                pixel_byte_array += (pixels_per_row - width) * 4;
+            }
         }
     } else if (format == GL_BGR) {
-        for (auto i = 0; i < width * height * 3; i += 3) {
-            u32 b = pixel_byte_array[i + 0];
-            u32 g = pixel_byte_array[i + 1];
-            u32 r = pixel_byte_array[i + 2];
-            u32 a = 255;
-
-            u32 pixel = ((a << 24) | (r << 16) | (g << 8) | b);
-            mip.pixel_data().append(pixel);
+        for (auto y = 0; y < height; y++) {
+            for (auto x = 0; x < width; x++) {
+                u32 b = *pixel_byte_array++;
+                u32 g = *pixel_byte_array++;
+                u32 r = *pixel_byte_array++;
+                u32 a = 255;
+
+                u32 pixel = ((a << 24) | (r << 16) | (g << 8) | b);
+                mip.pixel_data().append(pixel);
+            }
+
+            if (pixels_per_row > 0) {
+                pixel_byte_array += (pixels_per_row - width) * 3;
+            }
         }
     } else if (format == GL_RGB) {
-        for (auto i = 0; i < width * height * 3; i += 3) {
-            u32 r = pixel_byte_array[i + 0];
-            u32 g = pixel_byte_array[i + 1];
-            u32 b = pixel_byte_array[i + 2];
-            u32 a = 255;
-
-            u32 pixel = ((a << 24) | (r << 16) | (g << 8) | b);
-            mip.pixel_data().append(pixel);
+        for (auto y = 0; y < height; y++) {
+            for (auto x = 0; x < width; x++) {
+                u32 r = *pixel_byte_array++;
+                u32 g = *pixel_byte_array++;
+                u32 b = *pixel_byte_array++;
+                u32 a = 255;
+
+                u32 pixel = ((a << 24) | (r << 16) | (g << 8) | b);
+                mip.pixel_data().append(pixel);
+            }
+
+            if (pixels_per_row > 0) {
+                pixel_byte_array += (pixels_per_row - width) * 3;
+            }
         }
     } else {
         VERIFY_NOT_REACHED();

+ 1 - 1
Userland/Libraries/LibGL/Tex/Texture2D.h

@@ -35,7 +35,7 @@ public:
 
     virtual bool is_texture_2d() const override { return true; }
 
-    void upload_texture_data(GLenum target, GLint lod, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+    void upload_texture_data(GLenum target, GLint lod, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels, size_t pixels_per_row);
     void replace_sub_texture_data(GLint lod, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* data);
 
     MipMap const& mipmap(unsigned lod) const;