--- a/gfx/webrender_bindings/src/swgl_bindings.rs
+++ b/gfx/webrender_bindings/src/swgl_bindings.rs
@@ -20,18 +20,19 @@ pub extern "C" fn wr_swgl_destroy_contex
}
#[no_mangle]
pub extern "C" fn wr_swgl_make_current(ctx: *mut c_void) {
swgl::Context::from(ctx).make_current();
}
#[no_mangle]
-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);
+pub extern "C" fn wr_swgl_init_default_framebuffer(ctx: *mut c_void, width: i32, height: i32,
+ stride: i32, buf: *mut c_void) {
+ swgl::Context::from(ctx).init_default_framebuffer(width, height, stride, buf);
}
#[derive(Debug)]
pub struct SwTile {
x: i32,
y: i32,
fbo_id: u32,
color_id: u32,
@@ -306,26 +307,28 @@ impl Compositor for SwCompositor {
if let Some(surface) = self.surfaces.get_mut(&id.surface_id) {
let texs = self.gl.gen_textures(2);
let color_id = texs[0];
self.gl.set_texture_buffer(
color_id,
gl::RGBA8,
surface.tile_size.width,
surface.tile_size.height,
+ 0,
ptr::null_mut(),
0,
0,
);
let depth_id = texs[1];
self.gl.set_texture_buffer(
depth_id,
gl::DEPTH_COMPONENT16,
surface.tile_size.width,
surface.tile_size.height,
+ 0,
ptr::null_mut(),
0,
0,
);
let fbo_id = self.gl.gen_framebuffers(1)[0];
self.gl.bind_framebuffer(gl::DRAW_FRAMEBUFFER, fbo_id);
self.gl
.framebuffer_texture_2d(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, color_id, 0);
@@ -425,25 +428,27 @@ impl Compositor for SwCompositor {
}
}
}
self.gl.set_texture_buffer(
tile.color_id,
gl::RGBA8,
valid_rect.size.width,
valid_rect.size.height,
+ valid_rect.size.width * 4,
buf,
surface.tile_size.width,
surface.tile_size.height,
);
self.gl.set_texture_buffer(
tile.depth_id,
gl::DEPTH_COMPONENT16,
valid_rect.size.width,
valid_rect.size.height,
+ 0,
ptr::null_mut(),
surface.tile_size.width,
surface.tile_size.height,
);
surface_info.fbo_id = tile.fbo_id;
surface_info.origin -= valid_rect.origin.to_vector();
}
}
@@ -458,33 +463,34 @@ impl Compositor for SwCompositor {
};
let id = self.cur_tile;
if let Some(surface) = self.surfaces.get_mut(&id.surface_id) {
if let Some(tile) = surface.tiles.iter().find(|t| t.x == id.x && t.y == id.y) {
if tile.valid_rect.is_empty() {
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 {
native_gl.unmap_buffer(gl::PIXEL_UNPACK_BUFFER);
0 as *mut c_void
} else {
swbuf
};
let dirty = tile.dirty_rect;
let src = unsafe {
(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,
)
};
native_gl.active_texture(gl::TEXTURE0);
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(
gl::TEXTURE_2D,
0,
dirty.origin.x,
dirty.origin.y,
dirty.size.width,
dirty.size.height,
gl::BGRA,
@@ -529,17 +535,17 @@ impl Compositor for SwCompositor {
}
self.frame_surfaces.push((id, position, clip_rect));
}
fn end_frame(&mut self) {
if let Some(compositor) = &mut self.compositor {
compositor.end_frame();
} 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 draw_tile = self.draw_tile.as_ref().unwrap();
draw_tile.enable(&viewport);
let mut blend = false;
native_gl.blend_func(gl::ONE, gl::ONE_MINUS_SRC_ALPHA);
for &(ref id, position, ref clip_rect) in &self.frame_surfaces {
if let Some(surface) = self.surfaces.get(id) {
if surface.is_opaque {
--- a/gfx/wr/swgl/src/gl.cc
+++ b/gfx/wr/swgl/src/gl.cc
@@ -221,16 +221,18 @@ TextureFilter gl_filter_to_texture_filte
struct Texture {
GLenum internal_format = 0;
int width = 0;
int height = 0;
int depth = 0;
char* buf = nullptr;
size_t buf_size = 0;
+ uint32_t buf_stride = 0;
+ uint8_t buf_bpp = 0;
GLenum min_filter = GL_NEAREST;
GLenum mag_filter = GL_LINEAR;
enum FLAGS {
SHOULD_FREE = 1 << 1,
};
int flags = SHOULD_FREE;
bool should_free() const { return bool(flags & SHOULD_FREE); }
@@ -270,76 +272,92 @@ struct Texture {
void disable_delayed_clear() {
if (cleared_rows) {
delete[] cleared_rows;
cleared_rows = nullptr;
delay_clear = 0;
}
}
- int bpp() const { return bytes_for_internal_format(internal_format); }
-
- size_t stride(int b = 0, int min_width = 0) const {
- return aligned_stride((b ? b : bpp()) * max(width, min_width));
- }
-
- size_t layer_stride(int b = 0, int min_width = 0, int min_height = 0) const {
- return stride(b ? b : bpp(), min_width) * max(height, min_height);
+ int bpp() const { return buf_bpp; }
+ void set_bpp() { buf_bpp = bytes_for_internal_format(internal_format); }
+
+ size_t stride() const { return buf_stride; }
+ void set_stride() { buf_stride = aligned_stride(buf_bpp * width); }
+
+ // Set an external backing buffer of this texture.
+ 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) {
+ // 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()) {
- 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) {
// 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.
char* new_buf = (char*)realloc(buf, size + sizeof(Float));
assert(new_buf);
if (new_buf) {
+ // Successfully reallocated the buffer, so go ahead and set it.
buf = new_buf;
buf_size = size;
return true;
}
+ // Allocation failed, so ensure we don't leave stale buffer state.
cleanup();
}
}
+ // Nothing changed...
return false;
}
void cleanup() {
if (buf && should_free()) {
free(buf);
buf = nullptr;
buf_size = 0;
+ buf_bpp = 0;
+ buf_stride = 0;
}
disable_delayed_clear();
}
~Texture() { cleanup(); }
IntRect bounds() const { return IntRect{0, 0, width, height}; }
// Find the valid sampling bounds relative to the requested region
IntRect sample_bounds(const IntRect& req, bool invertY = false) const {
IntRect bb = bounds().intersect(req).offset(-req.x0, -req.y0);
if (invertY) bb.invert_y(req.height());
return bb;
}
// Get a pointer for sampling at the given offset
- char* sample_ptr(int x, int y, int z, int bpp, size_t stride) const {
- 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());
+ char* sample_ptr(int x, int y, int z = 0) const {
+ return buf + (height * z + y) * stride() + x * bpp();
}
// Get a pointer for sampling the requested region and limit to the provided
// sampling bounds
char* sample_ptr(const IntRect& req, const IntRect& bounds, int z,
bool invertY = false) const {
// Offset the sample pointer by the clamped bounds
int x = req.x0 + bounds.x0;
@@ -372,29 +390,29 @@ struct Program {
~Program() {
delete impl;
}
};
// for GL defines to fully expand
#define CONCAT_KEY(prefix, x, y, z, w, ...) prefix##x##y##z##w
#define BLEND_KEY(...) CONCAT_KEY(BLEND_, __VA_ARGS__, 0, 0)
-#define FOR_EACH_BLEND_KEY(macro) \
- 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_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_ALPHA, 0, 0) macro( \
- GL_ZERO, GL_SRC_COLOR, 0, 0) macro(GL_ONE, GL_ONE, 0, 0) \
- macro(GL_ONE, GL_ONE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA) \
- macro(GL_ONE, GL_ZERO, 0, 0) macro( \
- GL_ONE_MINUS_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE) \
- macro(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, \
- 0, 0) \
- macro(GL_ONE, GL_ONE_MINUS_SRC1_COLOR, 0, 0)
+#define FOR_EACH_BLEND_KEY(macro) \
+ 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_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_ALPHA, 0, 0) \
+ macro(GL_ZERO, GL_SRC_COLOR, 0, 0) \
+ macro(GL_ONE, GL_ONE, 0, 0) \
+ macro(GL_ONE, GL_ONE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA) \
+ macro(GL_ONE, GL_ZERO, 0, 0) \
+ macro(GL_ONE_MINUS_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE) \
+ macro(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, 0, 0) \
+ macro(GL_ONE, GL_ONE_MINUS_SRC1_COLOR, 0, 0)
#define DEFINE_BLEND_KEY(...) BLEND_KEY(__VA_ARGS__),
enum BlendKey : uint8_t {
BLEND_KEY_NONE = 0,
FOR_EACH_BLEND_KEY(DEFINE_BLEND_KEY)
};
const size_t MAX_TEXTURE_UNITS = 16;
@@ -620,19 +638,18 @@ static inline void init_filter(S* s, Tex
s->filter = gl_filter_to_texture_filter(t.mag_filter);
}
template <typename S>
static inline void init_sampler(S* s, Texture& t) {
prepare_texture(t);
s->width = t.width;
s->height = t.height;
- int bpp = t.bpp();
- s->stride = t.stride(bpp);
- if (bpp >= 4) s->stride /= 4;
+ s->stride = t.stride();
+ if (t.bpp() >= 4) s->stride /= 4;
// Use uint32_t* for easier sampling, but need to cast to uint8_t* for formats
// with bpp < 4.
s->buf = (uint32_t*)t.buf;
s->format = gl_format_to_texture_format(t.internal_format);
}
template <typename S>
S* lookup_sampler(S* s, int texture) {
@@ -1279,35 +1296,39 @@ void TexStorage3D(GLenum target, GLint l
t.depth = depth;
}
t.disable_delayed_clear();
t.allocate(changed);
}
static void set_tex_storage(Texture& t, GLenum internal_format,
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) {
internal_format = remap_internal_format(internal_format);
bool changed = false;
if (t.width != width || t.height != height || t.depth != 0 ||
t.internal_format != internal_format) {
changed = true;
t.internal_format = internal_format;
t.width = width;
t.height = height;
t.depth = 0;
}
- if (t.should_free() != should_free || buf != nullptr) {
- if (t.should_free()) {
- t.cleanup();
- }
+ // If we are changed from an internally managed buffer to an externally
+ // supplied one or vice versa, ensure that we clean up old buffer state.
+ bool should_free = buf == nullptr;
+ if (t.should_free() != should_free) {
+ changed = true;
+ t.cleanup();
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.allocate(changed, min_width, min_height);
}
void TexStorage2D(GLenum target, GLint levels, GLenum internal_format,
GLsizei width, GLsizei height) {
assert(levels == 1);
@@ -1384,18 +1405,18 @@ void TexSubImage2D(GLenum target, GLint
assert(xoffset + width <= t.width);
assert(yoffset + height <= t.height);
assert(ctx->unpack_row_length == 0 || ctx->unpack_row_length >= width);
GLsizei row_length =
ctx->unpack_row_length != 0 ? ctx->unpack_row_length : width;
assert(t.internal_format == internal_format_for_data(format, ty));
int bpp = t.bpp();
if (!bpp || !t.buf) return;
- size_t dest_stride = t.stride(bpp);
- char* dest = t.sample_ptr(xoffset, yoffset, 0, bpp, dest_stride);
+ size_t dest_stride = t.stride();
+ char* dest = t.sample_ptr(xoffset, yoffset);
char* src = (char*)data;
for (int y = 0; y < height; y++) {
if (t.internal_format == GL_RGBA8 && format != GL_BGRA) {
copy_bgra8_to_rgba8((uint32_t*)dest, (uint32_t*)src, width);
} else {
memcpy(dest, src, width * bpp);
}
dest += dest_stride;
@@ -1430,19 +1451,19 @@ void TexSubImage3D(GLenum target, GLint
assert(t.internal_format == internal_format_for_data(format, ty));
}
int bpp = t.bpp();
if (!bpp || !t.buf) return;
char* src = (char*)data;
assert(xoffset + width <= t.width);
assert(yoffset + height <= t.height);
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++) {
- 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++) {
if (t.internal_format == GL_RGBA8 && format != GL_BGRA) {
copy_bgra8_to_rgba8((uint32_t*)dest, (uint32_t*)src, width);
} else {
memcpy(dest, src, width * bpp);
}
dest += dest_stride;
src += row_length * bpp;
@@ -1792,24 +1813,24 @@ static inline void clear_row(T* buf, siz
template <typename T>
static void clear_buffer(Texture& t, T value, int layer, IntRect bb,
int skip_start = 0, int skip_end = 0) {
if (!t.buf) return;
skip_start = max(skip_start, bb.x0);
skip_end = max(skip_end, skip_start);
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
// large "row" to avoid redundant setup from clearing each row individually.
if (bb.width() == t.width && bb.height() > 1 && skip_start >= skip_end) {
bb.x1 += (stride / sizeof(T)) * (bb.height() - 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);
for (int rows = bb.height(); rows > 0; rows--) {
if (bb.x0 < skip_start) {
clear_row(buf, skip_start - bb.x0, value, chunk);
}
if (skip_end < bb.x1) {
clear_row(buf + (skip_end - bb.x0), bb.x1 - skip_end, value, chunk);
}
@@ -1826,17 +1847,17 @@ static inline void clear_buffer(Texture&
}
template <typename T>
static inline void force_clear_row(Texture& t, int y, int skip_start = 0,
int skip_end = 0) {
assert(t.buf != nullptr);
assert(sizeof(T) == t.bpp());
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);
if (skip_start > 0) {
clear_row<T>(buf, skip_start, t.clear_val, chunk);
}
if (skip_end < t.width) {
clear_row<T>(buf + skip_end, t.width - skip_end, t.clear_val, chunk);
}
}
@@ -1909,58 +1930,56 @@ static void prepare_texture(Texture& t,
assert(false);
break;
}
}
}
extern "C" {
-void InitDefaultFramebuffer(int width, int height) {
+void InitDefaultFramebuffer(int width, int height, int stride, void* buf) {
Framebuffer& fb = ctx->framebuffers[0];
if (!fb.color_attachment) {
GenTextures(1, &fb.color_attachment);
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];
- if (colortex.width != width || colortex.height != height) {
- colortex.cleanup();
- set_tex_storage(colortex, GL_RGBA8, width, height);
- }
+ set_tex_storage(colortex, GL_RGBA8, width, height, buf, stride);
if (!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];
- if (depthtex.width != width || depthtex.height != height) {
- depthtex.cleanup();
- set_tex_storage(depthtex, GL_DEPTH_COMPONENT16, width, height);
- }
+ set_tex_storage(depthtex, GL_DEPTH_COMPONENT16, width, height);
}
void* GetColorBuffer(GLuint fbo, GLboolean flush, int32_t* width,
- int32_t* height) {
+ int32_t* height, int32_t* stride) {
Framebuffer* fb = ctx->framebuffers.find(fbo);
if (!fb || !fb->color_attachment) {
return nullptr;
}
Texture& colortex = ctx->textures[fb->color_attachment];
if (flush) {
prepare_texture(colortex);
}
*width = colortex.width;
*height = colortex.height;
+ *stride = colortex.stride();
return colortex.buf ? colortex.sample_ptr(0, 0, fb->layer) : nullptr;
}
void SetTextureBuffer(GLuint texid, GLenum internal_format, GLsizei width,
- GLsizei height, void* buf, GLsizei min_width,
- GLsizei min_height) {
+ GLsizei height, GLsizei stride, void* buf,
+ GLsizei min_width, GLsizei min_height) {
Texture& t = ctx->textures[texid];
- set_tex_storage(t, internal_format, width, height, !buf, buf, min_width,
- min_height);
+ set_tex_storage(t, internal_format, width, height, buf, stride,
+ min_width, min_height);
}
GLenum CheckFramebufferStatus(GLenum target) {
Framebuffer* fb = get_framebuffer(target);
if (!fb || !fb->color_attachment) {
return GL_FRAMEBUFFER_UNSUPPORTED;
}
return GL_FRAMEBUFFER_COMPLETE;
@@ -2056,18 +2075,18 @@ void ReadPixels(GLint x, GLint y, GLsize
assert(y + height <= t.height);
if (internal_format_for_data(format, type) != t.internal_format) {
debugf("mismatched format for read pixels: %x vs %x\n", t.internal_format,
internal_format_for_data(format, type));
assert(false);
}
int bpp = t.bpp();
char* dest = (char*)data;
- size_t src_stride = t.stride(bpp);
- char* src = t.sample_ptr(x, y, fb->layer, bpp, src_stride);
+ size_t src_stride = t.stride();
+ char* src = t.sample_ptr(x, y, fb->layer);
for (; height > 0; height--) {
if (t.internal_format == GL_RGBA8 && format != GL_BGRA) {
copy_bgra8_to_rgba8((uint32_t*)dest, (uint32_t*)src, width);
} else {
memcpy(dest, src, width * bpp);
}
dest += width * bpp;
src += src_stride;
@@ -2101,21 +2120,21 @@ void CopyImageSubData(GLuint srcName, GL
assert(srcDepth >= 0);
assert(srcX + srcWidth <= srctex.width);
assert(srcY + srcHeight <= srctex.height);
assert(srcZ + srcDepth <= max(srctex.depth, 1));
assert(dstX + srcWidth <= dsttex.width);
assert(dstY + srcHeight <= dsttex.height);
assert(dstZ + srcDepth <= max(dsttex.depth, 1));
int bpp = srctex.bpp();
- int src_stride = srctex.stride(bpp);
- int dest_stride = dsttex.stride(bpp);
+ int src_stride = srctex.stride();
+ int dest_stride = dsttex.stride();
for (int z = 0; z < srcDepth; z++) {
- char* dest = dsttex.sample_ptr(dstX, dstY, dstZ + z, bpp, dest_stride);
- char* src = srctex.sample_ptr(srcX, srcY, srcZ + z, bpp, src_stride);
+ char* dest = dsttex.sample_ptr(dstX, dstY, dstZ + z);
+ char* src = srctex.sample_ptr(srcX, srcY, srcZ + z);
for (int y = 0; y < srcHeight; y++) {
memcpy(dest, src, srcWidth * bpp);
dest += dest_stride;
src += src_stride;
}
}
}
@@ -2911,19 +2930,18 @@ static inline void draw_quad_spans(int n
// Vertex selection above should result in equal left and right start rows
assert(l0.y == r0.y);
// Find the start y, clip to within the clip rect, and round to row center.
float y = floor(max(l0.y, clipRect.y0) + 0.5f) + 0.5f;
// Initialize left and right edges from end points and start Y
Edge left(y, l0, l1, interp_outs[l0i], interp_outs[l1i]);
Edge right(y, r0, r1, interp_outs[r0i], interp_outs[r1i]);
// Get pointer to color buffer and depth buffer at current Y
- P* fbuf = (P*)colortex.sample_ptr(0, int(y), layer, sizeof(P));
- uint16_t* fdepth =
- (uint16_t*)depthtex.sample_ptr(0, int(y), 0, sizeof(uint16_t));
+ P* fbuf = (P*)colortex.sample_ptr(0, int(y), layer);
+ uint16_t* fdepth = (uint16_t*)depthtex.sample_ptr(0, int(y));
// Loop along advancing Ys, rasterizing spans at each row
float checkY = min(min(l1.y, r1.y), clipRect.y1);
for (;;) {
// Check if we maybe passed edge ends or outside clip rect...
if (y > checkY) {
// If we're outside the clip rect, we're done.
if (y > clipRect.y1) break;
// Helper to find the next non-duplicate vertex that doesn't loop back.
@@ -3095,18 +3113,18 @@ static inline void draw_quad_spans(int n
}
}
next_span:
// Advance Y and edge interpolants to next row.
y++;
left.nextRow();
right.nextRow();
// Advance buffers to next row.
- fbuf += colortex.stride(sizeof(P)) / sizeof(P);
- fdepth += depthtex.stride(sizeof(uint16_t)) / sizeof(uint16_t);
+ fbuf += colortex.stride() / sizeof(P);
+ fdepth += depthtex.stride() / sizeof(uint16_t);
}
}
// Draw perspective-correct spans for a convex quad that has been clipped to
// the near and far Z planes, possibly producing a clipped convex polygon with
// more than 4 sides. This assumes the Z value will vary across the spans and
// requires interpolants to factor in W values. This tends to be slower than
// the simpler 2D draw_quad_spans above, especially since we can't optimize the
@@ -3203,19 +3221,18 @@ static inline void draw_perspective_span
// Vertex selection above should result in equal left and right start rows
assert(l0.y == r0.y);
// Find the start y, clip to within the clip rect, and round to row center.
float y = floor(max(l0.y, clipRect.y0) + 0.5f) + 0.5f;
// Initialize left and right edges from end points and start Y
Edge left(y, l0, l1, interp_outs[l0i], interp_outs[l1i]);
Edge right(y, r0, r1, interp_outs[r0i], interp_outs[r1i]);
// Get pointer to color buffer and depth buffer at current Y
- P* fbuf = (P*)colortex.sample_ptr(0, int(y), layer, sizeof(P));
- uint16_t* fdepth =
- (uint16_t*)depthtex.sample_ptr(0, int(y), 0, sizeof(uint16_t));
+ P* fbuf = (P*)colortex.sample_ptr(0, int(y), layer);
+ uint16_t* fdepth = (uint16_t*)depthtex.sample_ptr(0, int(y));
// Loop along advancing Ys, rasterizing spans at each row
float checkY = min(min(l1.y, r1.y), clipRect.y1);
for (;;) {
// Check if we maybe passed edge ends or outside clip rect...
if (y > checkY) {
// If we're outside the clip rect, we're done.
if (y > clipRect.y1) break;
// Check if Y advanced past the end of the left edge
@@ -3314,18 +3331,18 @@ static inline void draw_perspective_span
draw_span<true, true>(buf, depth, span, packDepth);
}
}
// Advance Y and edge interpolants to next row.
y++;
left.nextRow();
right.nextRow();
// Advance buffers to next row.
- fbuf += colortex.stride(sizeof(P)) / sizeof(P);
- fdepth += depthtex.stride(sizeof(uint16_t)) / sizeof(uint16_t);
+ fbuf += colortex.stride() / sizeof(P);
+ fdepth += depthtex.stride() / sizeof(uint16_t);
}
}
// Clip a primitive against both sides of a view-frustum axis, producing
// intermediate vertexes with interpolated attributes that will no longer
// intersect the selected axis planes. This assumes the primitive is convex
// and should produce at most N+2 vertexes for each invocation (only in the
// worst case where one point falls outside on each of the opposite sides
@@ -3732,18 +3749,18 @@ static void scale_blit(Texture& srctex,
if (dstBounds.is_empty()) {
return;
}
// Compute final source bounds from clamped dest sampling bounds
srcBounds = IntRect(dstBounds)
.scale(dstWidth, dstHeight, srcWidth, srcHeight);
// Calculate source and dest pointers from clamped offsets
int bpp = srctex.bpp();
- int srcStride = srctex.stride(bpp);
- int destStride = dsttex.stride(bpp);
+ int srcStride = srctex.stride();
+ int destStride = dsttex.stride();
char* dest = dsttex.sample_ptr(dstReq, dstBounds, dstZ, invertY);
char* src = srctex.sample_ptr(srcReq, srcBounds, srcZ);
// Inverted Y must step downward along dest rows
if (invertY) {
destStride = -destStride;
}
int span = dstBounds.width();
int frac = 0;
@@ -3833,17 +3850,17 @@ static void linear_blit(Texture& srctex,
float(srcReq.height()) / dstReq.height());
// Skip to clamped source start
srcUV += srcDUV * vec2_scalar(dstBounds.x0, dstBounds.y0);
// Offset source UVs to texel centers and scale by lerp precision
srcUV = linearQuantize(srcUV + 0.5f, 128);
srcDUV *= 128.0f;
// Calculate dest pointer from clamped offsets
int bpp = dsttex.bpp();
- int destStride = dsttex.stride(bpp);
+ int destStride = dsttex.stride();
char* dest = dsttex.sample_ptr(dstReq, dstBounds, dstZ, invertY);
// Inverted Y must step downward along dest rows
if (invertY) {
destStride = -destStride;
}
int span = dstBounds.width();
for (int rows = dstBounds.height(); rows > 0; rows--) {
switch (bpp) {
@@ -3943,18 +3960,18 @@ void Composite(GLuint srcId, GLint srcX,
}
Texture& srctex = ctx->textures[srcId];
if (!srctex.buf) return;
prepare_texture(srctex);
Texture& dsttex = ctx->textures[fb.color_attachment];
if (!dsttex.buf) return;
assert(srctex.bpp() == 4);
const int bpp = 4;
- size_t src_stride = srctex.stride(bpp);
- size_t dest_stride = dsttex.stride(bpp);
+ size_t src_stride = srctex.stride();
+ size_t dest_stride = dsttex.stride();
if (srcY < 0) {
dstY -= srcY;
srcHeight += srcY;
srcY = 0;
}
if (dstY < 0) {
srcY -= dstY;
srcHeight += dstY;
@@ -3964,18 +3981,18 @@ void Composite(GLuint srcId, GLint srcX,
srcHeight = srctex.height - srcY;
}
if (dstY + srcHeight > dsttex.height) {
srcHeight = dsttex.height - dstY;
}
IntRect skip = {dstX, dstY, dstX + srcWidth, dstY + srcHeight};
prepare_texture(dsttex, &skip);
char* dest = dsttex.sample_ptr(dstX, flip ? dsttex.height - 1 - dstY : dstY,
- fb.layer, bpp, dest_stride);
- char* src = srctex.sample_ptr(srcX, srcY, 0, bpp, src_stride);
+ fb.layer);
+ char* src = srctex.sample_ptr(srcX, srcY);
if (flip) {
dest_stride = -dest_stride;
}
if (opaque) {
for (int y = 0; y < srcHeight; y++) {
memcpy(dest, src, srcWidth * bpp);
dest += dest_stride;
src += src_stride;