diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h index 7b2560173..1605fcdc4 100644 --- a/cogl/cogl/cogl-framebuffer-private.h +++ b/cogl/cogl/cogl-framebuffer-private.h @@ -378,7 +378,11 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, * This blits a region of the color buffer of the source buffer * to the destination buffer. This function should only be * called if the COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT feature is - * advertised. The two buffers must both be offscreen. + * advertised. + * + * The source and destination rectangles are defined in offscreen + * framebuffer orientation. When copying between an offscreen and + * onscreen framebuffers, the image is y-flipped accordingly. * * The two buffers must have the same value types (e.g. floating-point, * unsigned int, signed int, or fixed-point), but color formats do not @@ -393,14 +397,6 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, * scale the results it may make more sense to draw a primitive * instead. * - * We can only really support blitting between two offscreen buffers - * for this function on GLES2.0. This is because we effectively render - * upside down to offscreen buffers to maintain Cogl's representation - * of the texture coordinate system where 0,0 is the top left of the - * texture. If we were to blit from an offscreen to an onscreen buffer - * then we would need to mirror the blit along the x-axis but the GLES - * extension does not support this. - * * The GL function is documented to be affected by the scissor. This * function therefore ensure that an empty clip stack is flushed * before performing the blit which means the scissor is effectively diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c index 1c046476e..45c532cff 100644 --- a/cogl/cogl/cogl-framebuffer.c +++ b/cogl/cogl/cogl-framebuffer.c @@ -1352,15 +1352,12 @@ _cogl_blit_framebuffer (CoglFramebuffer *src, int height) { CoglContext *ctx = src->context; + int src_x1, src_y1, src_x2, src_y2; + int dst_x1, dst_y1, dst_x2, dst_y2; g_return_if_fail (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)); - /* We can only support blitting between offscreen buffers because - otherwise we would need to mirror the image and GLES2.0 doesn't - support this */ - g_return_if_fail (cogl_is_offscreen (src)); - g_return_if_fail (cogl_is_offscreen (dest)); /* The buffers must use the same premult convention */ g_return_if_fail ((src->internal_format & COGL_PREMULT_BIT) == (dest->internal_format & COGL_PREMULT_BIT)); @@ -1384,10 +1381,41 @@ _cogl_blit_framebuffer (CoglFramebuffer *src, * as changed */ ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_CLIP; - ctx->glBlitFramebuffer (src_x, src_y, - src_x + width, src_y + height, - dst_x, dst_y, - dst_x + width, dst_y + height, + /* Offscreens we do the normal way, onscreens need an y-flip. Even if + * we consider offscreens to be rendered upside-down, the offscreen + * orientation is in this function's API. */ + if (cogl_is_offscreen (src)) + { + src_x1 = src_x; + src_y1 = src_y; + src_x2 = src_x + width; + src_y2 = src_y + height; + } + else + { + src_x1 = src_x; + src_y1 = cogl_framebuffer_get_height (src) - src_y; + src_x2 = src_x + width; + src_y2 = src_y1 - height; + } + + if (cogl_is_offscreen (dest)) + { + dst_x1 = dst_x; + dst_y1 = dst_y; + dst_x2 = dst_x + width; + dst_y2 = dst_y + height; + } + else + { + dst_x1 = dst_x; + dst_y1 = cogl_framebuffer_get_height (dest) - dst_y; + dst_x2 = dst_x + width; + dst_y2 = dst_y1 - height; + } + + ctx->glBlitFramebuffer (src_x1, src_y1, src_x2, src_y2, + dst_x1, dst_y1, dst_x2, dst_y2, GL_COLOR_BUFFER_BIT, GL_NEAREST); } diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c index b8fd2f689..ec9230c6a 100644 --- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c +++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c @@ -385,12 +385,9 @@ _cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer, else { /* NB: Currently we only take advantage of binding separate - * read/write buffers for offscreen framebuffer blit - * purposes. */ + * read/write buffers for framebuffer blit purposes. */ g_return_if_fail (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)); - g_return_if_fail (draw_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN); - g_return_if_fail (read_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN); _cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER); _cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER);