Procházet zdrojové kódy

LibGL: Implement glReadPixels() stub with argument validation

Stephan Unverwerth před 4 roky
rodič
revize
d6c84ca4df

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

@@ -115,6 +115,29 @@ extern "C" {
 #define GL_COMPILE 0x1300
 #define GL_COMPILE 0x1300
 #define GL_COMPILE_AND_EXECUTE 0x1301
 #define GL_COMPILE_AND_EXECUTE 0x1301
 
 
+// Type enums
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+
+// Format enums
+#define GL_COLOR_INDEX 0x1900
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_BITMAP 0x1A00
+#define GL_STENCIL_INDEX 0x1901
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_RED 0x1903
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+
 // Lighting related defines
 // Lighting related defines
 #define GL_FLAT 0x1D00
 #define GL_FLAT 0x1D00
 #define GL_SMOOTH 0x1D01
 #define GL_SMOOTH 0x1D01
@@ -211,6 +234,7 @@ GLAPI void glShadeModel(GLenum mode);
 GLAPI void glAlphaFunc(GLenum func, GLclampf ref);
 GLAPI void glAlphaFunc(GLenum func, GLclampf ref);
 GLAPI void glHint(GLenum target, GLenum mode);
 GLAPI void glHint(GLenum target, GLenum mode);
 GLAPI void glReadBuffer(GLenum mode);
 GLAPI void glReadBuffer(GLenum mode);
+GLAPI void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

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

@@ -54,6 +54,7 @@ public:
     virtual void gl_alpha_func(GLenum func, GLclampf ref) = 0;
     virtual void gl_alpha_func(GLenum func, GLclampf ref) = 0;
     virtual void gl_hint(GLenum target, GLenum mode) = 0;
     virtual void gl_hint(GLenum target, GLenum mode) = 0;
     virtual void gl_read_buffer(GLenum mode) = 0;
     virtual void gl_read_buffer(GLenum mode) = 0;
+    virtual void gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) = 0;
 
 
     virtual void present() = 0;
     virtual void present() = 0;
 };
 };

+ 6 - 1
Userland/Libraries/LibGL/GLUtils.cpp

@@ -78,4 +78,9 @@ void glHint(GLenum target, GLenum mode)
 void glReadBuffer(GLenum mode)
 void glReadBuffer(GLenum mode)
 {
 {
     g_gl_context->gl_read_buffer(mode);
     g_gl_context->gl_read_buffer(mode);
-}
+}
+
+void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
+{
+    g_gl_context->gl_read_pixels(x, y, width, height, format, type, pixels);
+}

+ 69 - 0
Userland/Libraries/LibGL/SoftwareGLContext.cpp

@@ -1050,6 +1050,75 @@ void SoftwareGLContext::gl_read_buffer(GLenum mode)
     m_current_read_buffer = mode;
     m_current_read_buffer = mode;
 }
 }
 
 
+void SoftwareGLContext::gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
+{
+    if (m_in_draw_state) {
+        m_error = GL_INVALID_OPERATION;
+        return;
+    }
+
+    // Check for negative width/height omitted because GLsizei is unsigned in our implementation
+
+    if (format != GL_COLOR_INDEX
+        && format != GL_STENCIL_INDEX
+        && format != GL_DEPTH_COMPONENT
+        && format != GL_RED
+        && format != GL_GREEN
+        && format != GL_BLUE
+        && format != GL_ALPHA
+        && format != GL_RGB
+        && format != GL_RGBA
+        && format != GL_LUMINANCE
+        && format != GL_LUMINANCE_ALPHA) {
+        m_error = GL_INVALID_ENUM;
+        return;
+    }
+
+    if (type != GL_UNSIGNED_BYTE
+        && type != GL_BYTE
+        && type != GL_BITMAP
+        && type != GL_UNSIGNED_SHORT
+        && type != GL_SHORT
+        && type != GL_BLUE
+        && type != GL_UNSIGNED_INT
+        && type != GL_INT
+        && type != GL_FLOAT) {
+        m_error = GL_INVALID_ENUM;
+        return;
+    }
+
+    if (format == GL_COLOR_INDEX) {
+        // FIXME: We only support RGBA buffers for now.
+        // Once we add support for indexed color modes do the correct check here
+        m_error = GL_INVALID_OPERATION;
+        return;
+    }
+
+    if (format == GL_STENCIL_INDEX) {
+        // FIXME: We do not have stencil buffers yet
+        // Once we add support for stencil buffers do the correct check here
+        m_error = GL_INVALID_OPERATION;
+        return;
+    }
+
+    if (format == GL_DEPTH_COMPONENT) {
+        // FIXME: This check needs to be a bit more sophisticated. Currently the buffers
+        // are hardcoded. Once we add proper structures for them we need to correct this check
+        if (m_current_read_buffer == GL_FRONT
+            || m_current_read_buffer == GL_FRONT_LEFT
+            || m_current_read_buffer == GL_FRONT_RIGHT) {
+            // Error because only back buffer has a depth buffer
+            m_error = GL_INVALID_OPERATION;
+            return;
+        }
+    }
+
+    if (format == GL_DEPTH_COMPONENT) {
+        // Read from depth buffer
+        return;
+    }
+}
+
 void SoftwareGLContext::present()
 void SoftwareGLContext::present()
 {
 {
     m_rasterizer.blit_to(*m_frontbuffer);
     m_rasterizer.blit_to(*m_frontbuffer);

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

@@ -60,6 +60,7 @@ public:
     virtual void gl_alpha_func(GLenum func, GLclampf ref) override;
     virtual void gl_alpha_func(GLenum func, GLclampf ref) override;
     virtual void gl_hint(GLenum target, GLenum mode) override;
     virtual void gl_hint(GLenum target, GLenum mode) override;
     virtual void gl_read_buffer(GLenum mode) override;
     virtual void gl_read_buffer(GLenum mode) override;
+    virtual void gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) override;
 
 
     virtual void present() override;
     virtual void present() override;