static gboolean _cogl_blit_framebuffer_begin (CoglBlitData *data) { CoglHandle dst_fbo, src_fbo; gboolean ret; _COGL_GET_CONTEXT (ctx, FALSE); /* We can only blit between FBOs if both textures are the same format and the blit framebuffer extension is supported */ if ((cogl_texture_get_format (data->src_tex) & ~COGL_A_BIT) != (cogl_texture_get_format (data->dst_tex) & ~COGL_A_BIT) || !(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)) return FALSE; dst_fbo = _cogl_offscreen_new_to_texture_full (data->dst_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */); if (dst_fbo == COGL_INVALID_HANDLE) ret = FALSE; else { if (!cogl_framebuffer_allocate (dst_fbo, NULL)) ret = FALSE; else { src_fbo = _cogl_offscreen_new_to_texture_full (data->src_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */); if (src_fbo == COGL_INVALID_HANDLE) ret = FALSE; else { if (!cogl_framebuffer_allocate (src_fbo, NULL)) ret = FALSE; else _cogl_push_framebuffers (dst_fbo, src_fbo); cogl_handle_unref (src_fbo); } } cogl_handle_unref (dst_fbo); } return ret; }
static gboolean _cogl_blit_copy_tex_sub_image_begin (CoglBlitData *data) { CoglHandle fbo; _COGL_GET_CONTEXT (ctx, FALSE); /* This will only work if the target texture is a CoglTexture2D */ if (!cogl_is_texture_2d (data->dst_tex)) return FALSE; fbo = _cogl_offscreen_new_to_texture_full (data->src_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */); if (fbo == COGL_INVALID_HANDLE) return FALSE; if (!cogl_framebuffer_allocate (fbo, NULL)) { cogl_handle_unref (fbo); return FALSE; } cogl_push_framebuffer (fbo); cogl_handle_unref (fbo); return TRUE; }
static gboolean get_texture_bits_via_offscreen (CoglHandle texture_handle, int x, int y, int width, int height, guint8 *dst_bits, unsigned int dst_rowstride, CoglPixelFormat dst_format) { CoglFramebuffer *framebuffer; _COGL_GET_CONTEXT (ctx, FALSE); if (!cogl_features_available (COGL_FEATURE_OFFSCREEN)) return FALSE; framebuffer = _cogl_offscreen_new_to_texture_full (texture_handle, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0); if (framebuffer == NULL) return FALSE; cogl_push_framebuffer (framebuffer); _cogl_read_pixels_with_rowstride (x, y, width, height, COGL_READ_PIXELS_COLOR_BUFFER, dst_format, dst_bits, dst_rowstride); cogl_pop_framebuffer (); cogl_object_unref (framebuffer); return TRUE; }
static gboolean _cogl_blit_texture_render_begin (CoglBlitData *data) { CoglHandle fbo; CoglPipeline *pipeline; unsigned int dst_width, dst_height; _COGL_GET_CONTEXT (ctx, FALSE); fbo = _cogl_offscreen_new_to_texture_full (data->dst_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */); if (fbo == COGL_INVALID_HANDLE) return FALSE; if (!cogl_framebuffer_allocate (fbo, NULL)) { cogl_handle_unref (fbo); return FALSE; } cogl_push_framebuffer (fbo); cogl_handle_unref (fbo); dst_width = cogl_texture_get_width (data->dst_tex); dst_height = cogl_texture_get_height (data->dst_tex); /* Set up an orthographic projection so we can use pixel coordinates to render to the texture */ cogl_ortho (0, /* left */ dst_width, /* right */ dst_height, /* bottom */ 0, /* top */ -1, /* near */ 1 /* far */); /* We cache a pipeline used for migrating on to the context so that it doesn't have to continuously regenerate a shader program */ if (ctx->blit_texture_pipeline == NULL) { ctx->blit_texture_pipeline = cogl_pipeline_new (); cogl_pipeline_set_layer_filters (ctx->blit_texture_pipeline, 0, COGL_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST); /* Disable blending by just directly taking the contents of the source texture */ cogl_pipeline_set_blend (ctx->blit_texture_pipeline, "RGBA = ADD(SRC_COLOR, 0)", NULL); } pipeline = ctx->blit_texture_pipeline; cogl_pipeline_set_layer_texture (pipeline, 0, data->src_tex); _cogl_push_source (pipeline, FALSE); return TRUE; }