зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1646835 - allow specifying backing data and stride for SWGL default framebuffer. r=jimb
For performance reasons in SWGL software compositors. to avoid unnecessary full-screen copies of the framembuffer, we need to allow those compositors to map their underlying widget surfaces and pass that buffer to SWGL so that they can be directly rendered to. That also requires supporting custom strides, as we can't always enforce the particular layout of the buffers handed off to us. To that end, InitDefaultFramebuffer is generalized to take such information and then many places where we rely on a specific hard-coded SWGL-calculated stride have been altered to deal with a caller-supplied stride. Differential Revision: https://phabricator.services.mozilla.com/D80267
This commit is contained in:
Родитель
15c6376141
Коммит
62ba932186
|
@ -25,8 +25,9 @@ pub extern "C" fn wr_swgl_make_current(ctx: *mut c_void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wr_swgl_init_default_framebuffer(ctx: *mut c_void, width: i32, height: i32) {
|
pub extern "C" fn wr_swgl_init_default_framebuffer(ctx: *mut c_void, width: i32, height: i32,
|
||||||
swgl::Context::from(ctx).init_default_framebuffer(width, height);
|
stride: i32, buf: *mut c_void) {
|
||||||
|
swgl::Context::from(ctx).init_default_framebuffer(width, height, stride, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -311,6 +312,7 @@ impl Compositor for SwCompositor {
|
||||||
gl::RGBA8,
|
gl::RGBA8,
|
||||||
surface.tile_size.width,
|
surface.tile_size.width,
|
||||||
surface.tile_size.height,
|
surface.tile_size.height,
|
||||||
|
0,
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -321,6 +323,7 @@ impl Compositor for SwCompositor {
|
||||||
gl::DEPTH_COMPONENT16,
|
gl::DEPTH_COMPONENT16,
|
||||||
surface.tile_size.width,
|
surface.tile_size.width,
|
||||||
surface.tile_size.height,
|
surface.tile_size.height,
|
||||||
|
0,
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -430,6 +433,7 @@ impl Compositor for SwCompositor {
|
||||||
gl::RGBA8,
|
gl::RGBA8,
|
||||||
valid_rect.size.width,
|
valid_rect.size.width,
|
||||||
valid_rect.size.height,
|
valid_rect.size.height,
|
||||||
|
valid_rect.size.width * 4,
|
||||||
buf,
|
buf,
|
||||||
surface.tile_size.width,
|
surface.tile_size.width,
|
||||||
surface.tile_size.height,
|
surface.tile_size.height,
|
||||||
|
@ -439,6 +443,7 @@ impl Compositor for SwCompositor {
|
||||||
gl::DEPTH_COMPONENT16,
|
gl::DEPTH_COMPONENT16,
|
||||||
valid_rect.size.width,
|
valid_rect.size.width,
|
||||||
valid_rect.size.height,
|
valid_rect.size.height,
|
||||||
|
0,
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
surface.tile_size.width,
|
surface.tile_size.width,
|
||||||
surface.tile_size.height,
|
surface.tile_size.height,
|
||||||
|
@ -463,7 +468,8 @@ impl Compositor for SwCompositor {
|
||||||
if tile.valid_rect.is_empty() {
|
if tile.valid_rect.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let (swbuf, w, _) = self.gl.get_color_buffer(tile.fbo_id, true);
|
let (swbuf, _, _, stride) = self.gl.get_color_buffer(tile.fbo_id, true);
|
||||||
|
assert!(stride % 4 == 0);
|
||||||
let buf = if tile.pbo_id != 0 {
|
let buf = if tile.pbo_id != 0 {
|
||||||
native_gl.unmap_buffer(gl::PIXEL_UNPACK_BUFFER);
|
native_gl.unmap_buffer(gl::PIXEL_UNPACK_BUFFER);
|
||||||
0 as *mut c_void
|
0 as *mut c_void
|
||||||
|
@ -473,13 +479,13 @@ impl Compositor for SwCompositor {
|
||||||
let dirty = tile.dirty_rect;
|
let dirty = tile.dirty_rect;
|
||||||
let src = unsafe {
|
let src = unsafe {
|
||||||
(buf as *mut u32).offset(
|
(buf as *mut u32).offset(
|
||||||
(dirty.origin.y - tile.valid_rect.origin.y) as isize * w as isize
|
(dirty.origin.y - tile.valid_rect.origin.y) as isize * (stride / 4) as isize
|
||||||
+ (dirty.origin.x - tile.valid_rect.origin.x) as isize,
|
+ (dirty.origin.x - tile.valid_rect.origin.x) as isize,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
native_gl.active_texture(gl::TEXTURE0);
|
native_gl.active_texture(gl::TEXTURE0);
|
||||||
native_gl.bind_texture(gl::TEXTURE_2D, tile.tex_id);
|
native_gl.bind_texture(gl::TEXTURE_2D, tile.tex_id);
|
||||||
native_gl.pixel_store_i(gl::UNPACK_ROW_LENGTH, w);
|
native_gl.pixel_store_i(gl::UNPACK_ROW_LENGTH, stride / 4);
|
||||||
native_gl.tex_sub_image_2d_pbo(
|
native_gl.tex_sub_image_2d_pbo(
|
||||||
gl::TEXTURE_2D,
|
gl::TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
|
@ -534,7 +540,7 @@ impl Compositor for SwCompositor {
|
||||||
if let Some(compositor) = &mut self.compositor {
|
if let Some(compositor) = &mut self.compositor {
|
||||||
compositor.end_frame();
|
compositor.end_frame();
|
||||||
} else if let Some(native_gl) = &self.native_gl {
|
} else if let Some(native_gl) = &self.native_gl {
|
||||||
let (_, fw, fh) = self.gl.get_color_buffer(0, false);
|
let (_, fw, fh, _) = self.gl.get_color_buffer(0, false);
|
||||||
let viewport = DeviceIntRect::from_size(DeviceIntSize::new(fw, fh));
|
let viewport = DeviceIntRect::from_size(DeviceIntSize::new(fw, fh));
|
||||||
let draw_tile = self.draw_tile.as_ref().unwrap();
|
let draw_tile = self.draw_tile.as_ref().unwrap();
|
||||||
draw_tile.enable(&viewport);
|
draw_tile.enable(&viewport);
|
||||||
|
|
|
@ -226,6 +226,8 @@ struct Texture {
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
char* buf = nullptr;
|
char* buf = nullptr;
|
||||||
size_t buf_size = 0;
|
size_t buf_size = 0;
|
||||||
|
uint32_t buf_stride = 0;
|
||||||
|
uint8_t buf_bpp = 0;
|
||||||
GLenum min_filter = GL_NEAREST;
|
GLenum min_filter = GL_NEAREST;
|
||||||
GLenum mag_filter = GL_LINEAR;
|
GLenum mag_filter = GL_LINEAR;
|
||||||
|
|
||||||
|
@ -275,32 +277,54 @@ struct Texture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpp() const { return bytes_for_internal_format(internal_format); }
|
int bpp() const { return buf_bpp; }
|
||||||
|
void set_bpp() { buf_bpp = bytes_for_internal_format(internal_format); }
|
||||||
|
|
||||||
size_t stride(int b = 0, int min_width = 0) const {
|
size_t stride() const { return buf_stride; }
|
||||||
return aligned_stride((b ? b : bpp()) * max(width, min_width));
|
void set_stride() { buf_stride = aligned_stride(buf_bpp * width); }
|
||||||
}
|
|
||||||
|
|
||||||
size_t layer_stride(int b = 0, int min_width = 0, int min_height = 0) const {
|
// Set an external backing buffer of this texture.
|
||||||
return stride(b ? b : bpp(), min_width) * max(height, min_height);
|
void set_buffer(void* new_buf, size_t new_stride) {
|
||||||
|
assert(!should_free());
|
||||||
|
// Ensure that the supplied stride is at least as big as the internally
|
||||||
|
// calculated aligned stride.
|
||||||
|
set_bpp();
|
||||||
|
set_stride();
|
||||||
|
assert(new_stride >= buf_stride);
|
||||||
|
|
||||||
|
buf = (char *)new_buf;
|
||||||
|
buf_size = 0;
|
||||||
|
buf_stride = new_stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allocate(bool force = false, int min_width = 0, int min_height = 0) {
|
bool allocate(bool force = false, int min_width = 0, int min_height = 0) {
|
||||||
|
// Check if there is either no buffer currently or if we forced validation
|
||||||
|
// of the buffer size because some dimension might have changed.
|
||||||
if ((!buf || force) && should_free()) {
|
if ((!buf || force) && should_free()) {
|
||||||
size_t size = layer_stride(bpp(), min_width, min_height) * max(depth, 1);
|
// Initialize the buffer's BPP and stride, since they may have changed.
|
||||||
|
set_bpp();
|
||||||
|
set_stride();
|
||||||
|
// Compute new size based on the maximum potential stride, rather than
|
||||||
|
// the current stride, to hopefully avoid reallocations when size would
|
||||||
|
// otherwise change too much...
|
||||||
|
size_t max_stride = max(buf_stride, aligned_stride(buf_bpp * min_width));
|
||||||
|
size_t size = max_stride * max(height, min_height) * max(depth, 1);
|
||||||
if (!buf || size > buf_size) {
|
if (!buf || size > buf_size) {
|
||||||
// Allocate with a SIMD register-sized tail of padding at the end so we
|
// Allocate with a SIMD register-sized tail of padding at the end so we
|
||||||
// can safely read or write past the end of the texture with SIMD ops.
|
// can safely read or write past the end of the texture with SIMD ops.
|
||||||
char* new_buf = (char*)realloc(buf, size + sizeof(Float));
|
char* new_buf = (char*)realloc(buf, size + sizeof(Float));
|
||||||
assert(new_buf);
|
assert(new_buf);
|
||||||
if (new_buf) {
|
if (new_buf) {
|
||||||
|
// Successfully reallocated the buffer, so go ahead and set it.
|
||||||
buf = new_buf;
|
buf = new_buf;
|
||||||
buf_size = size;
|
buf_size = size;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// Allocation failed, so ensure we don't leave stale buffer state.
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Nothing changed...
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,6 +333,8 @@ struct Texture {
|
||||||
free(buf);
|
free(buf);
|
||||||
buf = nullptr;
|
buf = nullptr;
|
||||||
buf_size = 0;
|
buf_size = 0;
|
||||||
|
buf_bpp = 0;
|
||||||
|
buf_stride = 0;
|
||||||
}
|
}
|
||||||
disable_delayed_clear();
|
disable_delayed_clear();
|
||||||
}
|
}
|
||||||
|
@ -325,16 +351,8 @@ struct Texture {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a pointer for sampling at the given offset
|
// Get a pointer for sampling at the given offset
|
||||||
char* sample_ptr(int x, int y, int z, int bpp, size_t stride) const {
|
char* sample_ptr(int x, int y, int z = 0) const {
|
||||||
return buf + (height * z + y) * stride + x * bpp;
|
return buf + (height * z + y) * stride() + x * bpp();
|
||||||
}
|
|
||||||
|
|
||||||
char* sample_ptr(int x, int y, int z, int bpp) const {
|
|
||||||
return sample_ptr(x, y, z, bpp, stride(bpp));
|
|
||||||
}
|
|
||||||
|
|
||||||
char* sample_ptr(int x, int y, int z) const {
|
|
||||||
return sample_ptr(x, y, z, bpp());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a pointer for sampling the requested region and limit to the provided
|
// Get a pointer for sampling the requested region and limit to the provided
|
||||||
|
@ -377,19 +395,19 @@ struct Program {
|
||||||
// for GL defines to fully expand
|
// for GL defines to fully expand
|
||||||
#define CONCAT_KEY(prefix, x, y, z, w, ...) prefix##x##y##z##w
|
#define CONCAT_KEY(prefix, x, y, z, w, ...) prefix##x##y##z##w
|
||||||
#define BLEND_KEY(...) CONCAT_KEY(BLEND_, __VA_ARGS__, 0, 0)
|
#define BLEND_KEY(...) CONCAT_KEY(BLEND_, __VA_ARGS__, 0, 0)
|
||||||
#define FOR_EACH_BLEND_KEY(macro) \
|
#define FOR_EACH_BLEND_KEY(macro) \
|
||||||
macro(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE) \
|
macro(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE) \
|
||||||
macro(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, 0, 0) \
|
macro(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, 0, 0) \
|
||||||
macro(GL_ZERO, GL_ONE_MINUS_SRC_COLOR, 0, 0) \
|
macro(GL_ZERO, GL_ONE_MINUS_SRC_COLOR, 0, 0) \
|
||||||
macro(GL_ZERO, GL_ONE_MINUS_SRC_COLOR, GL_ZERO, GL_ONE) \
|
macro(GL_ZERO, GL_ONE_MINUS_SRC_COLOR, GL_ZERO, GL_ONE) \
|
||||||
macro(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, 0, 0) macro( \
|
macro(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, 0, 0) \
|
||||||
GL_ZERO, GL_SRC_COLOR, 0, 0) macro(GL_ONE, GL_ONE, 0, 0) \
|
macro(GL_ZERO, GL_SRC_COLOR, 0, 0) \
|
||||||
macro(GL_ONE, GL_ONE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA) \
|
macro(GL_ONE, GL_ONE, 0, 0) \
|
||||||
macro(GL_ONE, GL_ZERO, 0, 0) macro( \
|
macro(GL_ONE, GL_ONE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA) \
|
||||||
GL_ONE_MINUS_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE) \
|
macro(GL_ONE, GL_ZERO, 0, 0) \
|
||||||
macro(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, \
|
macro(GL_ONE_MINUS_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE) \
|
||||||
0, 0) \
|
macro(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, 0, 0) \
|
||||||
macro(GL_ONE, GL_ONE_MINUS_SRC1_COLOR, 0, 0)
|
macro(GL_ONE, GL_ONE_MINUS_SRC1_COLOR, 0, 0)
|
||||||
|
|
||||||
#define DEFINE_BLEND_KEY(...) BLEND_KEY(__VA_ARGS__),
|
#define DEFINE_BLEND_KEY(...) BLEND_KEY(__VA_ARGS__),
|
||||||
enum BlendKey : uint8_t {
|
enum BlendKey : uint8_t {
|
||||||
|
@ -625,9 +643,8 @@ static inline void init_sampler(S* s, Texture& t) {
|
||||||
prepare_texture(t);
|
prepare_texture(t);
|
||||||
s->width = t.width;
|
s->width = t.width;
|
||||||
s->height = t.height;
|
s->height = t.height;
|
||||||
int bpp = t.bpp();
|
s->stride = t.stride();
|
||||||
s->stride = t.stride(bpp);
|
if (t.bpp() >= 4) s->stride /= 4;
|
||||||
if (bpp >= 4) s->stride /= 4;
|
|
||||||
// Use uint32_t* for easier sampling, but need to cast to uint8_t* for formats
|
// Use uint32_t* for easier sampling, but need to cast to uint8_t* for formats
|
||||||
// with bpp < 4.
|
// with bpp < 4.
|
||||||
s->buf = (uint32_t*)t.buf;
|
s->buf = (uint32_t*)t.buf;
|
||||||
|
@ -1284,7 +1301,7 @@ void TexStorage3D(GLenum target, GLint levels, GLenum internal_format,
|
||||||
|
|
||||||
static void set_tex_storage(Texture& t, GLenum internal_format,
|
static void set_tex_storage(Texture& t, GLenum internal_format,
|
||||||
GLsizei width, GLsizei height,
|
GLsizei width, GLsizei height,
|
||||||
bool should_free = true, void* buf = nullptr,
|
void* buf = nullptr, GLsizei stride = 0,
|
||||||
GLsizei min_width = 0, GLsizei min_height = 0) {
|
GLsizei min_width = 0, GLsizei min_height = 0) {
|
||||||
internal_format = remap_internal_format(internal_format);
|
internal_format = remap_internal_format(internal_format);
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -1296,13 +1313,17 @@ static void set_tex_storage(Texture& t, GLenum internal_format,
|
||||||
t.height = height;
|
t.height = height;
|
||||||
t.depth = 0;
|
t.depth = 0;
|
||||||
}
|
}
|
||||||
if (t.should_free() != should_free || buf != nullptr) {
|
// If we are changed from an internally managed buffer to an externally
|
||||||
if (t.should_free()) {
|
// supplied one or vice versa, ensure that we clean up old buffer state.
|
||||||
t.cleanup();
|
bool should_free = buf == nullptr;
|
||||||
}
|
if (t.should_free() != should_free) {
|
||||||
|
changed = true;
|
||||||
|
t.cleanup();
|
||||||
t.set_should_free(should_free);
|
t.set_should_free(should_free);
|
||||||
t.buf = (char*)buf;
|
}
|
||||||
t.buf_size = 0;
|
// If now an external buffer, explicitly set it...
|
||||||
|
if (!should_free) {
|
||||||
|
t.set_buffer(buf, stride);
|
||||||
}
|
}
|
||||||
t.disable_delayed_clear();
|
t.disable_delayed_clear();
|
||||||
t.allocate(changed, min_width, min_height);
|
t.allocate(changed, min_width, min_height);
|
||||||
|
@ -1389,8 +1410,8 @@ void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
assert(t.internal_format == internal_format_for_data(format, ty));
|
assert(t.internal_format == internal_format_for_data(format, ty));
|
||||||
int bpp = t.bpp();
|
int bpp = t.bpp();
|
||||||
if (!bpp || !t.buf) return;
|
if (!bpp || !t.buf) return;
|
||||||
size_t dest_stride = t.stride(bpp);
|
size_t dest_stride = t.stride();
|
||||||
char* dest = t.sample_ptr(xoffset, yoffset, 0, bpp, dest_stride);
|
char* dest = t.sample_ptr(xoffset, yoffset);
|
||||||
char* src = (char*)data;
|
char* src = (char*)data;
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
if (t.internal_format == GL_RGBA8 && format != GL_BGRA) {
|
if (t.internal_format == GL_RGBA8 && format != GL_BGRA) {
|
||||||
|
@ -1435,9 +1456,9 @@ void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
assert(xoffset + width <= t.width);
|
assert(xoffset + width <= t.width);
|
||||||
assert(yoffset + height <= t.height);
|
assert(yoffset + height <= t.height);
|
||||||
assert(zoffset + depth <= t.depth);
|
assert(zoffset + depth <= t.depth);
|
||||||
size_t dest_stride = t.stride(bpp);
|
size_t dest_stride = t.stride();
|
||||||
for (int z = 0; z < depth; z++) {
|
for (int z = 0; z < depth; z++) {
|
||||||
char* dest = t.sample_ptr(xoffset, yoffset, zoffset + z, bpp, dest_stride);
|
char* dest = t.sample_ptr(xoffset, yoffset, zoffset + z);
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
if (t.internal_format == GL_RGBA8 && format != GL_BGRA) {
|
if (t.internal_format == GL_RGBA8 && format != GL_BGRA) {
|
||||||
copy_bgra8_to_rgba8((uint32_t*)dest, (uint32_t*)src, width);
|
copy_bgra8_to_rgba8((uint32_t*)dest, (uint32_t*)src, width);
|
||||||
|
@ -1797,14 +1818,14 @@ static void clear_buffer(Texture& t, T value, int layer, IntRect bb,
|
||||||
skip_start = max(skip_start, bb.x0);
|
skip_start = max(skip_start, bb.x0);
|
||||||
skip_end = max(skip_end, skip_start);
|
skip_end = max(skip_end, skip_start);
|
||||||
assert(sizeof(T) == t.bpp());
|
assert(sizeof(T) == t.bpp());
|
||||||
size_t stride = t.stride(sizeof(T));
|
size_t stride = t.stride();
|
||||||
// When clearing multiple full-width rows, collapse them into a single
|
// When clearing multiple full-width rows, collapse them into a single
|
||||||
// large "row" to avoid redundant setup from clearing each row individually.
|
// large "row" to avoid redundant setup from clearing each row individually.
|
||||||
if (bb.width() == t.width && bb.height() > 1 && skip_start >= skip_end) {
|
if (bb.width() == t.width && bb.height() > 1 && skip_start >= skip_end) {
|
||||||
bb.x1 += (stride / sizeof(T)) * (bb.height() - 1);
|
bb.x1 += (stride / sizeof(T)) * (bb.height() - 1);
|
||||||
bb.y1 = bb.y0 + 1;
|
bb.y1 = bb.y0 + 1;
|
||||||
}
|
}
|
||||||
T* buf = (T*)t.sample_ptr(bb.x0, bb.y0, layer, sizeof(T), stride);
|
T* buf = (T*)t.sample_ptr(bb.x0, bb.y0, layer);
|
||||||
uint32_t chunk = clear_chunk(value);
|
uint32_t chunk = clear_chunk(value);
|
||||||
for (int rows = bb.height(); rows > 0; rows--) {
|
for (int rows = bb.height(); rows > 0; rows--) {
|
||||||
if (bb.x0 < skip_start) {
|
if (bb.x0 < skip_start) {
|
||||||
|
@ -1831,7 +1852,7 @@ static inline void force_clear_row(Texture& t, int y, int skip_start = 0,
|
||||||
assert(t.buf != nullptr);
|
assert(t.buf != nullptr);
|
||||||
assert(sizeof(T) == t.bpp());
|
assert(sizeof(T) == t.bpp());
|
||||||
assert(skip_start <= skip_end);
|
assert(skip_start <= skip_end);
|
||||||
T* buf = (T*)t.sample_ptr(0, y, 0, sizeof(T));
|
T* buf = (T*)t.sample_ptr(0, y);
|
||||||
uint32_t chunk = clear_chunk((T)t.clear_val);
|
uint32_t chunk = clear_chunk((T)t.clear_val);
|
||||||
if (skip_start > 0) {
|
if (skip_start > 0) {
|
||||||
clear_row<T>(buf, skip_start, t.clear_val, chunk);
|
clear_row<T>(buf, skip_start, t.clear_val, chunk);
|
||||||
|
@ -1914,29 +1935,26 @@ static void prepare_texture(Texture& t, const IntRect* skip) {
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
void InitDefaultFramebuffer(int width, int height) {
|
void InitDefaultFramebuffer(int width, int height, int stride, void* buf) {
|
||||||
Framebuffer& fb = ctx->framebuffers[0];
|
Framebuffer& fb = ctx->framebuffers[0];
|
||||||
if (!fb.color_attachment) {
|
if (!fb.color_attachment) {
|
||||||
GenTextures(1, &fb.color_attachment);
|
GenTextures(1, &fb.color_attachment);
|
||||||
fb.layer = 0;
|
fb.layer = 0;
|
||||||
}
|
}
|
||||||
|
// If the dimensions or buffer properties changed, we need to reallocate
|
||||||
|
// the underlying storage for the color buffer texture.
|
||||||
Texture& colortex = ctx->textures[fb.color_attachment];
|
Texture& colortex = ctx->textures[fb.color_attachment];
|
||||||
if (colortex.width != width || colortex.height != height) {
|
set_tex_storage(colortex, GL_RGBA8, width, height, buf, stride);
|
||||||
colortex.cleanup();
|
|
||||||
set_tex_storage(colortex, GL_RGBA8, width, height);
|
|
||||||
}
|
|
||||||
if (!fb.depth_attachment) {
|
if (!fb.depth_attachment) {
|
||||||
GenTextures(1, &fb.depth_attachment);
|
GenTextures(1, &fb.depth_attachment);
|
||||||
}
|
}
|
||||||
|
// Ensure dimensions of the depth buffer match the color buffer.
|
||||||
Texture& depthtex = ctx->textures[fb.depth_attachment];
|
Texture& depthtex = ctx->textures[fb.depth_attachment];
|
||||||
if (depthtex.width != width || depthtex.height != height) {
|
set_tex_storage(depthtex, GL_DEPTH_COMPONENT16, width, height);
|
||||||
depthtex.cleanup();
|
|
||||||
set_tex_storage(depthtex, GL_DEPTH_COMPONENT16, width, height);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* GetColorBuffer(GLuint fbo, GLboolean flush, int32_t* width,
|
void* GetColorBuffer(GLuint fbo, GLboolean flush, int32_t* width,
|
||||||
int32_t* height) {
|
int32_t* height, int32_t* stride) {
|
||||||
Framebuffer* fb = ctx->framebuffers.find(fbo);
|
Framebuffer* fb = ctx->framebuffers.find(fbo);
|
||||||
if (!fb || !fb->color_attachment) {
|
if (!fb || !fb->color_attachment) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1947,15 +1965,16 @@ void* GetColorBuffer(GLuint fbo, GLboolean flush, int32_t* width,
|
||||||
}
|
}
|
||||||
*width = colortex.width;
|
*width = colortex.width;
|
||||||
*height = colortex.height;
|
*height = colortex.height;
|
||||||
|
*stride = colortex.stride();
|
||||||
return colortex.buf ? colortex.sample_ptr(0, 0, fb->layer) : nullptr;
|
return colortex.buf ? colortex.sample_ptr(0, 0, fb->layer) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetTextureBuffer(GLuint texid, GLenum internal_format, GLsizei width,
|
void SetTextureBuffer(GLuint texid, GLenum internal_format, GLsizei width,
|
||||||
GLsizei height, void* buf, GLsizei min_width,
|
GLsizei height, GLsizei stride, void* buf,
|
||||||
GLsizei min_height) {
|
GLsizei min_width, GLsizei min_height) {
|
||||||
Texture& t = ctx->textures[texid];
|
Texture& t = ctx->textures[texid];
|
||||||
set_tex_storage(t, internal_format, width, height, !buf, buf, min_width,
|
set_tex_storage(t, internal_format, width, height, buf, stride,
|
||||||
min_height);
|
min_width, min_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum CheckFramebufferStatus(GLenum target) {
|
GLenum CheckFramebufferStatus(GLenum target) {
|
||||||
|
@ -2061,8 +2080,8 @@ void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
|
||||||
}
|
}
|
||||||
int bpp = t.bpp();
|
int bpp = t.bpp();
|
||||||
char* dest = (char*)data;
|
char* dest = (char*)data;
|
||||||
size_t src_stride = t.stride(bpp);
|
size_t src_stride = t.stride();
|
||||||
char* src = t.sample_ptr(x, y, fb->layer, bpp, src_stride);
|
char* src = t.sample_ptr(x, y, fb->layer);
|
||||||
for (; height > 0; height--) {
|
for (; height > 0; height--) {
|
||||||
if (t.internal_format == GL_RGBA8 && format != GL_BGRA) {
|
if (t.internal_format == GL_RGBA8 && format != GL_BGRA) {
|
||||||
copy_bgra8_to_rgba8((uint32_t*)dest, (uint32_t*)src, width);
|
copy_bgra8_to_rgba8((uint32_t*)dest, (uint32_t*)src, width);
|
||||||
|
@ -2106,11 +2125,11 @@ void CopyImageSubData(GLuint srcName, GLenum srcTarget, UNUSED GLint srcLevel,
|
||||||
assert(dstY + srcHeight <= dsttex.height);
|
assert(dstY + srcHeight <= dsttex.height);
|
||||||
assert(dstZ + srcDepth <= max(dsttex.depth, 1));
|
assert(dstZ + srcDepth <= max(dsttex.depth, 1));
|
||||||
int bpp = srctex.bpp();
|
int bpp = srctex.bpp();
|
||||||
int src_stride = srctex.stride(bpp);
|
int src_stride = srctex.stride();
|
||||||
int dest_stride = dsttex.stride(bpp);
|
int dest_stride = dsttex.stride();
|
||||||
for (int z = 0; z < srcDepth; z++) {
|
for (int z = 0; z < srcDepth; z++) {
|
||||||
char* dest = dsttex.sample_ptr(dstX, dstY, dstZ + z, bpp, dest_stride);
|
char* dest = dsttex.sample_ptr(dstX, dstY, dstZ + z);
|
||||||
char* src = srctex.sample_ptr(srcX, srcY, srcZ + z, bpp, src_stride);
|
char* src = srctex.sample_ptr(srcX, srcY, srcZ + z);
|
||||||
for (int y = 0; y < srcHeight; y++) {
|
for (int y = 0; y < srcHeight; y++) {
|
||||||
memcpy(dest, src, srcWidth * bpp);
|
memcpy(dest, src, srcWidth * bpp);
|
||||||
dest += dest_stride;
|
dest += dest_stride;
|
||||||
|
@ -2916,9 +2935,8 @@ static inline void draw_quad_spans(int nump, Point2D p[4], uint16_t z,
|
||||||
Edge left(y, l0, l1, interp_outs[l0i], interp_outs[l1i]);
|
Edge left(y, l0, l1, interp_outs[l0i], interp_outs[l1i]);
|
||||||
Edge right(y, r0, r1, interp_outs[r0i], interp_outs[r1i]);
|
Edge right(y, r0, r1, interp_outs[r0i], interp_outs[r1i]);
|
||||||
// Get pointer to color buffer and depth buffer at current Y
|
// Get pointer to color buffer and depth buffer at current Y
|
||||||
P* fbuf = (P*)colortex.sample_ptr(0, int(y), layer, sizeof(P));
|
P* fbuf = (P*)colortex.sample_ptr(0, int(y), layer);
|
||||||
uint16_t* fdepth =
|
uint16_t* fdepth = (uint16_t*)depthtex.sample_ptr(0, int(y));
|
||||||
(uint16_t*)depthtex.sample_ptr(0, int(y), 0, sizeof(uint16_t));
|
|
||||||
// Loop along advancing Ys, rasterizing spans at each row
|
// Loop along advancing Ys, rasterizing spans at each row
|
||||||
float checkY = min(min(l1.y, r1.y), clipRect.y1);
|
float checkY = min(min(l1.y, r1.y), clipRect.y1);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -3100,8 +3118,8 @@ static inline void draw_quad_spans(int nump, Point2D p[4], uint16_t z,
|
||||||
left.nextRow();
|
left.nextRow();
|
||||||
right.nextRow();
|
right.nextRow();
|
||||||
// Advance buffers to next row.
|
// Advance buffers to next row.
|
||||||
fbuf += colortex.stride(sizeof(P)) / sizeof(P);
|
fbuf += colortex.stride() / sizeof(P);
|
||||||
fdepth += depthtex.stride(sizeof(uint16_t)) / sizeof(uint16_t);
|
fdepth += depthtex.stride() / sizeof(uint16_t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3208,9 +3226,8 @@ static inline void draw_perspective_spans(int nump, Point3D* p,
|
||||||
Edge left(y, l0, l1, interp_outs[l0i], interp_outs[l1i]);
|
Edge left(y, l0, l1, interp_outs[l0i], interp_outs[l1i]);
|
||||||
Edge right(y, r0, r1, interp_outs[r0i], interp_outs[r1i]);
|
Edge right(y, r0, r1, interp_outs[r0i], interp_outs[r1i]);
|
||||||
// Get pointer to color buffer and depth buffer at current Y
|
// Get pointer to color buffer and depth buffer at current Y
|
||||||
P* fbuf = (P*)colortex.sample_ptr(0, int(y), layer, sizeof(P));
|
P* fbuf = (P*)colortex.sample_ptr(0, int(y), layer);
|
||||||
uint16_t* fdepth =
|
uint16_t* fdepth = (uint16_t*)depthtex.sample_ptr(0, int(y));
|
||||||
(uint16_t*)depthtex.sample_ptr(0, int(y), 0, sizeof(uint16_t));
|
|
||||||
// Loop along advancing Ys, rasterizing spans at each row
|
// Loop along advancing Ys, rasterizing spans at each row
|
||||||
float checkY = min(min(l1.y, r1.y), clipRect.y1);
|
float checkY = min(min(l1.y, r1.y), clipRect.y1);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -3319,8 +3336,8 @@ static inline void draw_perspective_spans(int nump, Point3D* p,
|
||||||
left.nextRow();
|
left.nextRow();
|
||||||
right.nextRow();
|
right.nextRow();
|
||||||
// Advance buffers to next row.
|
// Advance buffers to next row.
|
||||||
fbuf += colortex.stride(sizeof(P)) / sizeof(P);
|
fbuf += colortex.stride() / sizeof(P);
|
||||||
fdepth += depthtex.stride(sizeof(uint16_t)) / sizeof(uint16_t);
|
fdepth += depthtex.stride() / sizeof(uint16_t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3737,8 +3754,8 @@ static void scale_blit(Texture& srctex, const IntRect& srcReq, int srcZ,
|
||||||
.scale(dstWidth, dstHeight, srcWidth, srcHeight);
|
.scale(dstWidth, dstHeight, srcWidth, srcHeight);
|
||||||
// Calculate source and dest pointers from clamped offsets
|
// Calculate source and dest pointers from clamped offsets
|
||||||
int bpp = srctex.bpp();
|
int bpp = srctex.bpp();
|
||||||
int srcStride = srctex.stride(bpp);
|
int srcStride = srctex.stride();
|
||||||
int destStride = dsttex.stride(bpp);
|
int destStride = dsttex.stride();
|
||||||
char* dest = dsttex.sample_ptr(dstReq, dstBounds, dstZ, invertY);
|
char* dest = dsttex.sample_ptr(dstReq, dstBounds, dstZ, invertY);
|
||||||
char* src = srctex.sample_ptr(srcReq, srcBounds, srcZ);
|
char* src = srctex.sample_ptr(srcReq, srcBounds, srcZ);
|
||||||
// Inverted Y must step downward along dest rows
|
// Inverted Y must step downward along dest rows
|
||||||
|
@ -3838,7 +3855,7 @@ static void linear_blit(Texture& srctex, const IntRect& srcReq, int srcZ,
|
||||||
srcDUV *= 128.0f;
|
srcDUV *= 128.0f;
|
||||||
// Calculate dest pointer from clamped offsets
|
// Calculate dest pointer from clamped offsets
|
||||||
int bpp = dsttex.bpp();
|
int bpp = dsttex.bpp();
|
||||||
int destStride = dsttex.stride(bpp);
|
int destStride = dsttex.stride();
|
||||||
char* dest = dsttex.sample_ptr(dstReq, dstBounds, dstZ, invertY);
|
char* dest = dsttex.sample_ptr(dstReq, dstBounds, dstZ, invertY);
|
||||||
// Inverted Y must step downward along dest rows
|
// Inverted Y must step downward along dest rows
|
||||||
if (invertY) {
|
if (invertY) {
|
||||||
|
@ -3948,8 +3965,8 @@ void Composite(GLuint srcId, GLint srcX, GLint srcY, GLsizei srcWidth,
|
||||||
if (!dsttex.buf) return;
|
if (!dsttex.buf) return;
|
||||||
assert(srctex.bpp() == 4);
|
assert(srctex.bpp() == 4);
|
||||||
const int bpp = 4;
|
const int bpp = 4;
|
||||||
size_t src_stride = srctex.stride(bpp);
|
size_t src_stride = srctex.stride();
|
||||||
size_t dest_stride = dsttex.stride(bpp);
|
size_t dest_stride = dsttex.stride();
|
||||||
if (srcY < 0) {
|
if (srcY < 0) {
|
||||||
dstY -= srcY;
|
dstY -= srcY;
|
||||||
srcHeight += srcY;
|
srcHeight += srcY;
|
||||||
|
@ -3969,8 +3986,8 @@ void Composite(GLuint srcId, GLint srcX, GLint srcY, GLsizei srcWidth,
|
||||||
IntRect skip = {dstX, dstY, dstX + srcWidth, dstY + srcHeight};
|
IntRect skip = {dstX, dstY, dstX + srcWidth, dstY + srcHeight};
|
||||||
prepare_texture(dsttex, &skip);
|
prepare_texture(dsttex, &skip);
|
||||||
char* dest = dsttex.sample_ptr(dstX, flip ? dsttex.height - 1 - dstY : dstY,
|
char* dest = dsttex.sample_ptr(dstX, flip ? dsttex.height - 1 - dstY : dstY,
|
||||||
fb.layer, bpp, dest_stride);
|
fb.layer);
|
||||||
char* src = srctex.sample_ptr(srcX, srcY, 0, bpp, src_stride);
|
char* src = srctex.sample_ptr(srcX, srcY);
|
||||||
if (flip) {
|
if (flip) {
|
||||||
dest_stride = -dest_stride;
|
dest_stride = -dest_stride;
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,18 +253,20 @@ extern "C" {
|
||||||
fn GetString(name: GLenum) -> *const c_char;
|
fn GetString(name: GLenum) -> *const c_char;
|
||||||
fn GetStringi(name: GLenum, index: GLuint) -> *const c_char;
|
fn GetStringi(name: GLenum, index: GLuint) -> *const c_char;
|
||||||
fn GetError() -> GLenum;
|
fn GetError() -> GLenum;
|
||||||
fn InitDefaultFramebuffer(width: i32, height: i32);
|
fn InitDefaultFramebuffer(width: i32, height: i32, stride: i32, buf: *mut c_void);
|
||||||
fn GetColorBuffer(
|
fn GetColorBuffer(
|
||||||
fbo: GLuint,
|
fbo: GLuint,
|
||||||
flush: GLboolean,
|
flush: GLboolean,
|
||||||
width: *mut i32,
|
width: *mut i32,
|
||||||
height: *mut i32,
|
height: *mut i32,
|
||||||
|
stride: *mut i32,
|
||||||
) -> *mut c_void;
|
) -> *mut c_void;
|
||||||
fn SetTextureBuffer(
|
fn SetTextureBuffer(
|
||||||
tex: GLuint,
|
tex: GLuint,
|
||||||
internal_format: GLenum,
|
internal_format: GLenum,
|
||||||
width: GLsizei,
|
width: GLsizei,
|
||||||
height: GLsizei,
|
height: GLsizei,
|
||||||
|
stride: GLsizei,
|
||||||
buf: *mut c_void,
|
buf: *mut c_void,
|
||||||
min_width: GLsizei,
|
min_width: GLsizei,
|
||||||
min_height: GLsizei,
|
min_height: GLsizei,
|
||||||
|
@ -313,18 +315,19 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_default_framebuffer(&self, width: i32, height: i32) {
|
pub fn init_default_framebuffer(&self, width: i32, height: i32, stride: i32, buf: *mut c_void) {
|
||||||
unsafe {
|
unsafe {
|
||||||
InitDefaultFramebuffer(width, height);
|
InitDefaultFramebuffer(width, height, stride, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_color_buffer(&self, fbo: GLuint, flush: bool) -> (*mut c_void, i32, i32) {
|
pub fn get_color_buffer(&self, fbo: GLuint, flush: bool) -> (*mut c_void, i32, i32, i32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut width: i32 = 0;
|
let mut width: i32 = 0;
|
||||||
let mut height: i32 = 0;
|
let mut height: i32 = 0;
|
||||||
let data_ptr = GetColorBuffer(fbo, flush as GLboolean, &mut width, &mut height);
|
let mut stride: i32 = 0;
|
||||||
(data_ptr, width, height)
|
let data_ptr = GetColorBuffer(fbo, flush as GLboolean, &mut width, &mut height, &mut stride);
|
||||||
|
(data_ptr, width, height, stride)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +337,7 @@ impl Context {
|
||||||
internal_format: GLenum,
|
internal_format: GLenum,
|
||||||
width: GLsizei,
|
width: GLsizei,
|
||||||
height: GLsizei,
|
height: GLsizei,
|
||||||
|
stride: GLsizei,
|
||||||
buf: *mut c_void,
|
buf: *mut c_void,
|
||||||
min_width: GLsizei,
|
min_width: GLsizei,
|
||||||
min_height: GLsizei,
|
min_height: GLsizei,
|
||||||
|
@ -344,6 +348,7 @@ impl Context {
|
||||||
internal_format,
|
internal_format,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
stride,
|
||||||
buf,
|
buf,
|
||||||
min_width,
|
min_width,
|
||||||
min_height,
|
min_height,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче