mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-20 09:49:15 +03:00
LibGL+LibSoftGPU: Implement glDrawPixels
depth buffer support
This enabled writing directly to the depth buffer, and allows games like Grim Fandango to render their pre-baked depth buffers correctly!
This commit is contained in:
parent
ca78327a96
commit
8efd6bc878
Notes:
sideshowbarker
2024-07-18 00:54:03 +09:00
Author: https://github.com/gmta Commit: https://github.com/SerenityOS/serenity/commit/8efd6bc8785 Pull-request: https://github.com/SerenityOS/serenity/pull/11834 Reviewed-by: https://github.com/Quaker762 ✅ Reviewed-by: https://github.com/sunverwerth ✅
@ -2243,26 +2243,42 @@ void SoftwareGLContext::gl_draw_pixels(GLsizei width, GLsizei height, GLenum for
|
||||
|
||||
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) {
|
||||
dbgln_if(GL_DEBUG, "gl_draw_pixels(): support for format {:#x} not implemented", format);
|
||||
return;
|
||||
} else if (type != GL_UNSIGNED_BYTE) {
|
||||
dbgln_if(GL_DEBUG, "gl_draw_pixels(): support for type {:#x} not implemented", type);
|
||||
// FIXME: we only support RGBA + UNSIGNED_BYTE and DEPTH_COMPONENT + UNSIGNED_SHORT, implement all combinations!
|
||||
if (!((format == GL_RGBA && type == GL_UNSIGNED_BYTE) || (format == GL_DEPTH_COMPONENT && type == GL_UNSIGNED_SHORT))) {
|
||||
dbgln_if(GL_DEBUG, "gl_draw_pixels(): support for format {:#x} and/or type {:#x} not implemented", 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 pixel parameters such as GL_UNPACK_ALIGNMENT
|
||||
|
||||
// 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++)));
|
||||
if (format == GL_RGBA) {
|
||||
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();
|
||||
|
||||
m_rasterizer.blit_to_color_buffer_at_raster_position(bitmap);
|
||||
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_to_color_buffer_at_raster_position(bitmap);
|
||||
} else if (format == GL_DEPTH_COMPONENT) {
|
||||
Vector<float> depth_values;
|
||||
depth_values.ensure_capacity(width * height);
|
||||
|
||||
auto depth_data = static_cast<u16 const*>(data);
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
auto u16_value = *(depth_data++);
|
||||
auto float_value = static_cast<float>(u16_value) / NumericLimits<u16>::max();
|
||||
depth_values.append(float_value);
|
||||
}
|
||||
}
|
||||
|
||||
m_rasterizer.blit_to_depth_buffer_at_raster_position(depth_values, width, height);
|
||||
} else {
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
void SoftwareGLContext::gl_depth_range(GLdouble min, GLdouble max)
|
||||
|
@ -992,6 +992,26 @@ void Device::blit_to_color_buffer_at_raster_position(Gfx::Bitmap const& source)
|
||||
painter.blit({ blit_rect.x(), blit_rect.y() }, source, source.rect(), 1.0f, true);
|
||||
}
|
||||
|
||||
void Device::blit_to_depth_buffer_at_raster_position(Vector<float> const& depth_values, size_t width, size_t height)
|
||||
{
|
||||
if (!m_raster_position.valid)
|
||||
return;
|
||||
|
||||
auto const raster_rect = raster_rect_in_target_coordinates({ width, height });
|
||||
auto const y1 = raster_rect.y();
|
||||
auto const y2 = y1 + height;
|
||||
auto const x1 = raster_rect.x();
|
||||
int const x2 = x1 + width;
|
||||
|
||||
auto index = 0;
|
||||
for (int y = y2 - 1; y >= y1; --y) {
|
||||
auto depth_line = m_depth_buffer->scanline(y);
|
||||
for (int x = x1; x < x2; ++x) {
|
||||
depth_line[x] = depth_values.at(index++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Device::blit_to(Gfx::Bitmap& target)
|
||||
{
|
||||
wait_for_all_threads();
|
||||
|
@ -105,6 +105,7 @@ public:
|
||||
void clear_depth(float);
|
||||
void blit_to(Gfx::Bitmap&);
|
||||
void blit_to_color_buffer_at_raster_position(Gfx::Bitmap const&);
|
||||
void blit_to_depth_buffer_at_raster_position(Vector<float> const&, size_t, size_t);
|
||||
void wait_for_all_threads() const;
|
||||
void set_options(const RasterizerOptions&);
|
||||
void set_light_model_params(const LightModelParameters&);
|
||||
|
Loading…
Reference in New Issue
Block a user