From 8ab410a536237dcf0491ba15c91c3db68b352a24 Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Thu, 1 Sep 2022 13:30:24 +0200 Subject: [PATCH] LibGL: Implement `glGetTexImage` The plumbing was already there in LibGPU, so all that was left was to implement the API :^) --- Userland/Libraries/LibGL/GL/gl.h | 1 + Userland/Libraries/LibGL/GLAPI.cpp | 5 ++++ Userland/Libraries/LibGL/GLContext.h | 1 + Userland/Libraries/LibGL/Tex/Texture2D.cpp | 8 ++++++ Userland/Libraries/LibGL/Tex/Texture2D.h | 1 + Userland/Libraries/LibGL/Texture.cpp | 30 ++++++++++++++++++++++ 6 files changed, 46 insertions(+) diff --git a/Userland/Libraries/LibGL/GL/gl.h b/Userland/Libraries/LibGL/GL/gl.h index 0358133e1c..9d1afa1f71 100644 --- a/Userland/Libraries/LibGL/GL/gl.h +++ b/Userland/Libraries/LibGL/GL/gl.h @@ -739,6 +739,7 @@ GLAPI void glTexGenfv(GLenum coord, GLenum pname, GLfloat const* params); GLAPI void glTexGeni(GLenum coord, GLenum pname, GLint param); GLAPI void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); GLAPI void glRecti(GLint x1, GLint y1, GLint x2, GLint y2); +GLAPI void glGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, void* pixels); GLAPI void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params); GLAPI void glPointSize(GLfloat size); GLAPI void glClipPlane(GLenum plane, GLdouble const* equation); diff --git a/Userland/Libraries/LibGL/GLAPI.cpp b/Userland/Libraries/LibGL/GLAPI.cpp index 575349f4fa..37b145512c 100644 --- a/Userland/Libraries/LibGL/GLAPI.cpp +++ b/Userland/Libraries/LibGL/GLAPI.cpp @@ -449,6 +449,11 @@ GLubyte const* glGetString(GLenum name) return g_gl_context->gl_get_string(name); } +void glGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, void* pixels) +{ + g_gl_context->gl_get_tex_image(target, level, format, type, pixels); +} + void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params) { g_gl_context->gl_get_tex_parameter_integerv(target, level, pname, params); diff --git a/Userland/Libraries/LibGL/GLContext.h b/Userland/Libraries/LibGL/GLContext.h index 9afaa508a2..13f523475a 100644 --- a/Userland/Libraries/LibGL/GLContext.h +++ b/Userland/Libraries/LibGL/GLContext.h @@ -194,6 +194,7 @@ public: void gl_light_model(GLenum pname, GLfloat x, GLfloat y, GLfloat z, GLfloat w); void gl_bitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte const* bitmap); void gl_copy_tex_image_2d(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + void gl_get_tex_image(GLenum target, GLint level, GLenum format, GLenum type, void* pixels); void gl_get_tex_parameter_integerv(GLenum target, GLint level, GLenum pname, GLint* params); void gl_rect(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); void gl_tex_gen(GLenum coord, GLenum pname, GLint param); diff --git a/Userland/Libraries/LibGL/Tex/Texture2D.cpp b/Userland/Libraries/LibGL/Tex/Texture2D.cpp index 49e6b33bc2..d3abc4fd33 100644 --- a/Userland/Libraries/LibGL/Tex/Texture2D.cpp +++ b/Userland/Libraries/LibGL/Tex/Texture2D.cpp @@ -11,6 +11,14 @@ namespace GL { +void Texture2D::download_texture_data(GLuint lod, GPU::ImageDataLayout output_layout, GLvoid* pixels) +{ + if (device_image().is_null()) + return; + + device_image()->read_texels(0, lod, { 0, 0, 0 }, pixels, output_layout); +} + void Texture2D::upload_texture_data(GLuint lod, GLenum internal_format, GPU::ImageDataLayout input_layout, GLvoid const* pixels) { // NOTE: Some target, format, and internal formats are currently unsupported. diff --git a/Userland/Libraries/LibGL/Tex/Texture2D.h b/Userland/Libraries/LibGL/Tex/Texture2D.h index 5ef8a3b740..0a886fa3a6 100644 --- a/Userland/Libraries/LibGL/Tex/Texture2D.h +++ b/Userland/Libraries/LibGL/Tex/Texture2D.h @@ -27,6 +27,7 @@ public: virtual bool is_texture_2d() const override { return true; } + void download_texture_data(GLuint lod, GPU::ImageDataLayout output_layout, GLvoid* pixels); void upload_texture_data(GLuint lod, GLenum internal_format, GPU::ImageDataLayout input_layout, GLvoid const* pixels); void replace_sub_texture_data(GLuint lod, GPU::ImageDataLayout input_layout, Vector3 const& output_offset, GLvoid const* pixels); diff --git a/Userland/Libraries/LibGL/Texture.cpp b/Userland/Libraries/LibGL/Texture.cpp index f6afb81bd1..477fe61e3d 100644 --- a/Userland/Libraries/LibGL/Texture.cpp +++ b/Userland/Libraries/LibGL/Texture.cpp @@ -143,6 +143,36 @@ void GLContext::gl_gen_textures(GLsizei n, GLuint* textures) } } +void GLContext::gl_get_tex_image(GLenum target, GLint level, GLenum format, GLenum type, void* pixels) +{ + RETURN_WITH_ERROR_IF(level < 0 || level > Texture2D::LOG2_MAX_TEXTURE_SIZE, GL_INVALID_VALUE); + auto pixel_type_or_error = get_validated_pixel_type(target, GL_NONE, format, type); + RETURN_WITH_ERROR_IF(pixel_type_or_error.is_error(), pixel_type_or_error.release_error().code()); + + auto texture_2d = m_active_texture_unit->texture_2d_target_texture(); + VERIFY(!texture_2d.is_null()); + + u32 width = texture_2d->width_at_lod(level); + u32 height = texture_2d->height_at_lod(level); + + GPU::ImageDataLayout output_layout = { + .pixel_type = pixel_type_or_error.release_value(), + .packing = get_packing_specification(PackingType::Pack), + .dimensions = { + .width = width, + .height = height, + .depth = 1, + }, + .selection = { + .width = width, + .height = height, + .depth = 1, + }, + }; + + texture_2d->download_texture_data(level, output_layout, pixels); +} + void GLContext::gl_get_tex_parameter_integerv(GLenum target, GLint level, GLenum pname, GLint* params) { RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);