1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 17:17:44 +00:00

LibGL: Implement glDrawPixels and add stub for glBitmap

This commit is contained in:
Jelle Raaijmakers 2021-12-01 17:19:22 +01:00 committed by Andreas Kling
parent c2960e68a8
commit 401472c9a4
7 changed files with 149 additions and 1 deletions

View file

@ -201,6 +201,18 @@ extern "C" {
// Source pixel data format
#define GL_UNSIGNED_BYTE 0x1401
#define GL_UNSIGNED_BYTE_3_3_2 0x8032
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
#define GL_UNSIGNED_INT_8_8_8_8 0x8035
#define GL_UNSIGNED_INT_10_10_10_2 0x8036
#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
// Stencil buffer operations
#define GL_KEEP 0x1E00
@ -450,6 +462,7 @@ GLAPI void glColorPointer(GLint size, GLenum type, GLsizei stride, const void* p
GLAPI void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void* pointer);
GLAPI void glDrawArrays(GLenum mode, GLint first, GLsizei count);
GLAPI void glDrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices);
GLAPI void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data);
GLAPI void glDepthRange(GLdouble nearVal, GLdouble farVal);
GLAPI void glDepthFunc(GLenum func);
GLAPI void glPolygonMode(GLenum face, GLenum mode);
@ -475,6 +488,7 @@ GLAPI void glMaterialfv(GLenum face, GLenum pname, GLfloat const* params);
GLAPI void glLineWidth(GLfloat width);
GLAPI void glPushAttrib(GLbitfield mask);
GLAPI void glPopAttrib();
GLAPI void glBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte const* bitmap);
#ifdef __cplusplus
}

View file

@ -79,6 +79,7 @@ public:
virtual void gl_tex_coord_pointer(GLint size, GLenum type, GLsizei stride, const void* pointer) = 0;
virtual void gl_draw_arrays(GLenum mode, GLint first, GLsizei count) = 0;
virtual void gl_draw_elements(GLenum mode, GLsizei count, GLenum type, const void* indices) = 0;
virtual void gl_draw_pixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data) = 0;
virtual void gl_color_mask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) = 0;
virtual void gl_get_booleanv(GLenum pname, GLboolean* data) = 0;
virtual void gl_get_doublev(GLenum pname, GLdouble* params) = 0;
@ -102,6 +103,7 @@ public:
virtual void gl_push_attrib(GLbitfield mask) = 0;
virtual void gl_pop_attrib() = 0;
virtual void gl_light_model(GLenum pname, GLfloat x, GLfloat y, GLfloat z, GLfloat w) = 0;
virtual void gl_bitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte const* bitmap) = 0;
virtual void present() = 0;
};

View file

@ -9,6 +9,16 @@
extern GL::GLContext* g_gl_context;
void glBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte const* bitmap)
{
g_gl_context->gl_bitmap(width, height, xorig, yorig, xmove, ymove, bitmap);
}
void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data)
{
g_gl_context->gl_draw_pixels(width, height, format, type, data);
}
void glLineWidth(GLfloat width)
{
g_gl_context->gl_line_width(width);

View file

@ -1926,6 +1926,106 @@ void SoftwareGLContext::gl_draw_elements(GLenum mode, GLsizei count, GLenum type
glEnd();
}
void SoftwareGLContext::gl_draw_pixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data)
{
APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_draw_pixels, width, height, format, type, data);
RETURN_WITH_ERROR_IF(!(format == GL_COLOR_INDEX
|| format == GL_STENCIL_INDEX
|| format == GL_DEPTH_COMPONENT
|| format == GL_RGBA
|| format == GL_BGRA
|| format == GL_RED
|| format == GL_GREEN
|| format == GL_BLUE
|| format == GL_ALPHA
|| format == GL_RGB
|| format == GL_BGR
|| format == GL_LUMINANCE
|| format == GL_LUMINANCE_ALPHA),
GL_INVALID_ENUM);
RETURN_WITH_ERROR_IF(!(type == GL_UNSIGNED_BYTE
|| type == GL_BYTE
|| type == GL_BITMAP
|| type == GL_UNSIGNED_SHORT
|| type == GL_SHORT
|| type == GL_UNSIGNED_INT
|| type == GL_INT
|| type == GL_FLOAT
|| type == GL_UNSIGNED_BYTE_3_3_2
|| type == GL_UNSIGNED_BYTE_2_3_3_REV
|| type == GL_UNSIGNED_SHORT_5_6_5
|| type == GL_UNSIGNED_SHORT_5_6_5_REV
|| type == GL_UNSIGNED_SHORT_4_4_4_4
|| type == GL_UNSIGNED_SHORT_4_4_4_4_REV
|| type == GL_UNSIGNED_SHORT_5_5_5_1
|| type == GL_UNSIGNED_SHORT_1_5_5_5_REV
|| type == GL_UNSIGNED_INT_8_8_8_8
|| type == GL_UNSIGNED_INT_8_8_8_8_REV
|| type == GL_UNSIGNED_INT_10_10_10_2
|| type == GL_UNSIGNED_INT_2_10_10_10_REV),
GL_INVALID_ENUM);
RETURN_WITH_ERROR_IF(type == GL_BITMAP && !(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX), GL_INVALID_ENUM);
RETURN_WITH_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
// FIXME: GL_INVALID_OPERATION is generated if format is GL_STENCIL_INDEX and there is no stencil buffer
// FIXME: GL_INVALID_OPERATION is generated if format is GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_RGB, GL_RGBA,
// GL_BGR, GL_BGRA, GL_LUMINANCE, or GL_LUMINANCE_ALPHA, and the GL is in color index mode
RETURN_WITH_ERROR_IF(format != GL_RGB
&& (type == GL_UNSIGNED_BYTE_3_3_2
|| type == GL_UNSIGNED_BYTE_2_3_3_REV
|| type == GL_UNSIGNED_SHORT_5_6_5
|| type == GL_UNSIGNED_SHORT_5_6_5_REV),
GL_INVALID_OPERATION);
RETURN_WITH_ERROR_IF(!(format == GL_RGBA || format == GL_BGRA)
&& (type == GL_UNSIGNED_SHORT_4_4_4_4
|| type == GL_UNSIGNED_SHORT_4_4_4_4_REV
|| type == GL_UNSIGNED_SHORT_5_5_5_1
|| type == GL_UNSIGNED_SHORT_1_5_5_5_REV
|| type == GL_UNSIGNED_INT_8_8_8_8
|| type == GL_UNSIGNED_INT_8_8_8_8_REV
|| type == GL_UNSIGNED_INT_10_10_10_2
|| type == GL_UNSIGNED_INT_2_10_10_10_REV),
GL_INVALID_OPERATION);
// FIXME: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
// target and the buffer object's data store is currently mapped.
// FIXME: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
// target and the data would be unpacked from the buffer object such that the memory reads required would
// exceed the data store size.
// FIXME: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
// target and data is not evenly divisible into the number of bytes needed to store in memory a datum
// indicated by type.
RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
// FIXME: we only support RGBA + GL_UNSIGNED_BYTE, implement all the others!
if (format != GL_RGBA || type != GL_UNSIGNED_BYTE) {
dbgln("gl_draw_pixels: unsupported format {:#x} or type {:#x}", format, type);
return;
}
auto bitmap_or_error = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, { width, height });
RETURN_WITH_ERROR_IF(bitmap_or_error.is_error(), GL_OUT_OF_MEMORY);
auto bitmap = bitmap_or_error.release_value();
// FIXME: implement support for GL_UNPACK_ALIGNMENT and other pixel parameters
auto pixel_data = static_cast<u32 const*>(data);
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
bitmap->set_pixel(x, y, Color::from_rgba(*(pixel_data++)));
m_rasterizer.blit(
bitmap,
static_cast<int>(m_current_raster_position.window_coordinates.x()),
static_cast<int>(m_current_raster_position.window_coordinates.y()));
}
void SoftwareGLContext::gl_depth_range(GLdouble min, GLdouble max)
{
APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_depth_range, min, max);
@ -2366,6 +2466,15 @@ void SoftwareGLContext::gl_light_model(GLenum pname, GLfloat x, GLfloat y, GLflo
}
}
void SoftwareGLContext::gl_bitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte const* bitmap)
{
APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_bitmap, width, height, xorig, yorig, xmove, ymove, bitmap);
RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
// FIXME: implement
dbgln_if(GL_DEBUG, "SoftwareGLContext FIXME: implement gl_bitmap({}, {}, {}, {}, {}, {}, {})", width, height, xorig, yorig, xmove, ymove, bitmap);
}
void SoftwareGLContext::present()
{
m_rasterizer.blit_to(*m_frontbuffer);

View file

@ -90,6 +90,7 @@ public:
virtual void gl_tex_coord_pointer(GLint size, GLenum type, GLsizei stride, const void* pointer) override;
virtual void gl_draw_arrays(GLenum mode, GLint first, GLsizei count) override;
virtual void gl_draw_elements(GLenum mode, GLsizei count, GLenum type, const void* indices) override;
virtual void gl_draw_pixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data) override;
virtual void gl_color_mask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) override;
virtual void gl_get_booleanv(GLenum pname, GLboolean* data) override;
virtual void gl_get_doublev(GLenum pname, GLdouble* params) override;
@ -113,6 +114,7 @@ public:
virtual void gl_push_attrib(GLbitfield mask) override;
virtual void gl_pop_attrib() override;
virtual void gl_light_model(GLenum pname, GLfloat x, GLfloat y, GLfloat z, GLfloat w) override;
virtual void gl_bitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte const* bitmap) override;
virtual void present() override;
private:
@ -275,6 +277,7 @@ private:
decltype(&SoftwareGLContext::gl_depth_mask),
decltype(&SoftwareGLContext::gl_draw_arrays),
decltype(&SoftwareGLContext::gl_draw_elements),
decltype(&SoftwareGLContext::gl_draw_pixels),
decltype(&SoftwareGLContext::gl_depth_range),
decltype(&SoftwareGLContext::gl_polygon_offset),
decltype(&SoftwareGLContext::gl_scissor),
@ -286,7 +289,8 @@ private:
decltype(&SoftwareGLContext::gl_line_width),
decltype(&SoftwareGLContext::gl_push_attrib),
decltype(&SoftwareGLContext::gl_pop_attrib),
decltype(&SoftwareGLContext::gl_light_model)>;
decltype(&SoftwareGLContext::gl_light_model),
decltype(&SoftwareGLContext::gl_bitmap)>;
using ExtraSavedArguments = Variant<
FloatMatrix4x4>;

View file

@ -604,6 +604,14 @@ void SoftwareRasterizer::clear_depth(float depth)
m_depth_buffer->clear(depth);
}
void SoftwareRasterizer::blit(Gfx::Bitmap const& source, int x, int y)
{
wait_for_all_threads();
Gfx::Painter painter { *m_render_target };
painter.blit({ x, y }, source, source.rect(), 1.0f, true);
}
void SoftwareRasterizer::blit_to(Gfx::Bitmap& target)
{
wait_for_all_threads();

View file

@ -61,6 +61,7 @@ public:
void resize(const Gfx::IntSize& min_size);
void clear_color(const FloatVector4&);
void clear_depth(float);
void blit(Gfx::Bitmap const&, int x, int y);
void blit_to(Gfx::Bitmap&);
void wait_for_all_threads() const;
void set_options(const RasterizerOptions&);