summaryrefslogtreecommitdiff
path: root/cogl/cogl/cogl-blit.c
diff options
context:
space:
mode:
Diffstat (limited to 'cogl/cogl/cogl-blit.c')
-rw-r--r--cogl/cogl/cogl-blit.c441
1 files changed, 0 insertions, 441 deletions
diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c
deleted file mode 100644
index 57922f736..000000000
--- a/cogl/cogl/cogl-blit.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Cogl
- *
- * A Low Level GPU Graphics and Utilities API
- *
- * Copyright (C) 2011 Intel Corporation.
- * Copyright (C) 2019 DisplayLink (UK) Ltd.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#include "cogl-config.h"
-
-#include <string.h>
-
-#include "cogl-util.h"
-#include "cogl-blit.h"
-#include "cogl-context-private.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-texture-2d-private.h"
-#include "cogl-private.h"
-#include "cogl1-context.h"
-
-static const CoglBlitMode *_cogl_blit_default_mode = NULL;
-
-static gboolean
-_cogl_blit_texture_render_begin (CoglBlitData *data)
-{
- CoglContext *ctx = data->src_tex->context;
- CoglOffscreen *offscreen;
- CoglFramebuffer *fb;
- CoglPipeline *pipeline;
- unsigned int dst_width, dst_height;
- GError *ignore_error = NULL;
-
- offscreen = _cogl_offscreen_new_with_texture_full
- (data->dst_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */);
-
- fb = COGL_FRAMEBUFFER (offscreen);
- if (!cogl_framebuffer_allocate (fb, &ignore_error))
- {
- g_error_free (ignore_error);
- g_object_unref (fb);
- return FALSE;
- }
-
- data->dest_fb = fb;
-
- 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_framebuffer_orthographic (fb,
- 0, 0, dst_width, dst_height,
- -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 (ctx);
-
- 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);
-
- data->pipeline = pipeline;
-
- return TRUE;
-}
-
-static void
-_cogl_blit_texture_render_blit (CoglBlitData *data,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height)
-{
- cogl_framebuffer_draw_textured_rectangle (data->dest_fb,
- data->pipeline,
- dst_x, dst_y,
- dst_x + width,
- dst_y + height,
- src_x / (float) data->src_width,
- src_y / (float) data->src_height,
- (src_x + width) /
- (float) data->src_width,
- (src_y + height) /
- (float) data->src_height);
-}
-
-static void
-_cogl_blit_texture_render_end (CoglBlitData *data)
-{
- CoglContext *ctx = data->src_tex->context;
-
- /* Attach the target texture to the texture render pipeline so that
- we don't keep a reference to the source texture forever. This is
- assuming that the destination texture will live for a long time
- which is currently the case when cogl_blit_* is used from the
- atlas code. It may be better in future to keep around a set of
- dummy 1x1 textures for each texture target that we could bind
- instead. This would also be useful when using a pipeline as a
- hash table key such as for the ARBfp program cache. */
- cogl_pipeline_set_layer_texture (ctx->blit_texture_pipeline, 0,
- data->dst_tex);
-
- g_object_unref (data->dest_fb);
-}
-
-static gboolean
-_cogl_blit_framebuffer_begin (CoglBlitData *data)
-{
- CoglContext *ctx = data->src_tex->context;
- CoglOffscreen *dst_offscreen = NULL, *src_offscreen = NULL;
- CoglFramebuffer *dst_fb, *src_fb;
- GError *ignore_error = NULL;
-
- /* We can only blit between FBOs if both textures have the same
- premult convention and the blit framebuffer extension is
- supported. */
- if ((_cogl_texture_get_format (data->src_tex) & COGL_PREMULT_BIT) !=
- (_cogl_texture_get_format (data->dst_tex) & COGL_PREMULT_BIT) ||
- !cogl_has_feature (ctx, COGL_FEATURE_ID_BLIT_FRAMEBUFFER))
- return FALSE;
-
- dst_offscreen = _cogl_offscreen_new_with_texture_full
- (data->dst_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */);
-
- dst_fb = COGL_FRAMEBUFFER (dst_offscreen);
- if (!cogl_framebuffer_allocate (dst_fb, &ignore_error))
- {
- g_error_free (ignore_error);
- goto error;
- }
-
- src_offscreen= _cogl_offscreen_new_with_texture_full
- (data->src_tex,
- COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL,
- 0 /* level */);
-
- src_fb = COGL_FRAMEBUFFER (src_offscreen);
- if (!cogl_framebuffer_allocate (src_fb, &ignore_error))
- {
- g_error_free (ignore_error);
- goto error;
- }
-
- data->src_fb = src_fb;
- data->dest_fb = dst_fb;
-
- return TRUE;
-
-error:
-
- g_clear_object (&dst_offscreen);
- g_clear_object (&src_offscreen);
-
- return FALSE;
-}
-
-static void
-_cogl_blit_framebuffer_blit (CoglBlitData *data,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height)
-{
- cogl_blit_framebuffer (data->src_fb,
- data->dest_fb,
- src_x, src_y,
- dst_x, dst_y,
- width, height,
- NULL);
-}
-
-static void
-_cogl_blit_framebuffer_end (CoglBlitData *data)
-{
- g_object_unref (data->src_fb);
- g_object_unref (data->dest_fb);
-}
-
-static gboolean
-_cogl_blit_copy_tex_sub_image_begin (CoglBlitData *data)
-{
- CoglOffscreen *offscreen;
- CoglFramebuffer *fb;
- GError *ignore_error = NULL;
-
- /* This will only work if the target texture is a CoglTexture2D */
- if (!cogl_is_texture_2d (data->dst_tex))
- return FALSE;
-
- offscreen = _cogl_offscreen_new_with_texture_full
- (data->src_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */);
-
- fb = COGL_FRAMEBUFFER (offscreen);
- if (!cogl_framebuffer_allocate (fb, &ignore_error))
- {
- g_error_free (ignore_error);
- g_object_unref (fb);
- return FALSE;
- }
-
- data->src_fb = fb;
-
- return TRUE;
-}
-
-static void
-_cogl_blit_copy_tex_sub_image_blit (CoglBlitData *data,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height)
-{
- _cogl_texture_2d_copy_from_framebuffer (COGL_TEXTURE_2D (data->dst_tex),
- src_x, src_y,
- width, height,
- data->src_fb,
- dst_x, dst_y,
- 0); /* level */
-}
-
-static void
-_cogl_blit_copy_tex_sub_image_end (CoglBlitData *data)
-{
- g_object_unref (data->src_fb);
-}
-
-static gboolean
-_cogl_blit_get_tex_data_begin (CoglBlitData *data)
-{
- data->format = _cogl_texture_get_format (data->src_tex);
-
- g_return_val_if_fail (cogl_pixel_format_get_n_planes (data->format) == 1,
- FALSE);
-
- data->bpp = cogl_pixel_format_get_bytes_per_pixel (data->format, 0);
-
- data->image_data = g_malloc (data->bpp * data->src_width *
- data->src_height);
- cogl_texture_get_data (data->src_tex, data->format,
- data->src_width * data->bpp, data->image_data);
-
- return TRUE;
-}
-
-static void
-_cogl_blit_get_tex_data_blit (CoglBlitData *data,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height)
-{
- GError *ignore = NULL;
- int rowstride = data->src_width * data->bpp;
- int offset = rowstride * src_y + src_x * data->bpp;
-
- _cogl_texture_set_region (data->dst_tex,
- width, height,
- data->format,
- rowstride,
- data->image_data + offset,
- dst_x, dst_y,
- 0, /* level */
- &ignore);
- /* TODO: support chaining up errors during the blit */
-}
-
-static void
-_cogl_blit_get_tex_data_end (CoglBlitData *data)
-{
- g_free (data->image_data);
-}
-
-/* These should be specified in order of preference */
-static const CoglBlitMode
-_cogl_blit_modes[] =
- {
- {
- "texture-render",
- _cogl_blit_texture_render_begin,
- _cogl_blit_texture_render_blit,
- _cogl_blit_texture_render_end
- },
- {
- "framebuffer",
- _cogl_blit_framebuffer_begin,
- _cogl_blit_framebuffer_blit,
- _cogl_blit_framebuffer_end
- },
- {
- "copy-tex-sub-image",
- _cogl_blit_copy_tex_sub_image_begin,
- _cogl_blit_copy_tex_sub_image_blit,
- _cogl_blit_copy_tex_sub_image_end
- },
- {
- "get-tex-data",
- _cogl_blit_get_tex_data_begin,
- _cogl_blit_get_tex_data_blit,
- _cogl_blit_get_tex_data_end
- }
- };
-
-void
-_cogl_blit_begin (CoglBlitData *data,
- CoglTexture *dst_tex,
- CoglTexture *src_tex)
-{
- int i;
-
- if (_cogl_blit_default_mode == NULL)
- {
- const char *default_mode_string;
-
- /* Allow the default to be specified with an environment
- variable. For the time being these functions are only used
- when blitting between atlas textures so the environment
- variable is named to be specific to the atlas code. If we
- want to use the code in other places we should create another
- environment variable for each specific use case */
- if ((default_mode_string = g_getenv ("COGL_ATLAS_DEFAULT_BLIT_MODE")))
- {
- for (i = 0; i < G_N_ELEMENTS (_cogl_blit_modes); i++)
- if (!strcmp (_cogl_blit_modes[i].name, default_mode_string))
- {
- _cogl_blit_default_mode = _cogl_blit_modes + i;
- break;
- }
-
- if (i >= G_N_ELEMENTS (_cogl_blit_modes))
- {
- g_warning ("Unknown blit mode %s", default_mode_string);
- _cogl_blit_default_mode = _cogl_blit_modes;
- }
- }
- else
- /* Default to the first blit mode */
- _cogl_blit_default_mode = _cogl_blit_modes;
- }
-
- memset (data, 0, sizeof (CoglBlitData));
-
- data->dst_tex = dst_tex;
- data->src_tex = src_tex;
-
- data->src_width = cogl_texture_get_width (src_tex);
- data->src_height = cogl_texture_get_height (src_tex);
-
- /* Try the default blit mode first */
- if (!_cogl_blit_default_mode->begin_func (data))
- {
- COGL_NOTE (ATLAS, "Failed to set up blit mode %s",
- _cogl_blit_default_mode->name);
-
- /* Try all of the other modes in order */
- for (i = 0; i < G_N_ELEMENTS (_cogl_blit_modes); i++)
- if (_cogl_blit_modes + i != _cogl_blit_default_mode &&
- _cogl_blit_modes[i].begin_func (data))
- {
- /* Use this mode as the default from now on */
- _cogl_blit_default_mode = _cogl_blit_modes + i;
- break;
- }
- else
- COGL_NOTE (ATLAS,
- "Failed to set up blit mode %s",
- _cogl_blit_modes[i].name);
-
- /* The last blit mode can't fail so this should never happen */
- g_return_if_fail (i < G_N_ELEMENTS (_cogl_blit_modes));
- }
-
- data->blit_mode = _cogl_blit_default_mode;
-
- COGL_NOTE (ATLAS, "Setup blit using %s", _cogl_blit_default_mode->name);
-}
-
-void
-_cogl_blit (CoglBlitData *data,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height)
-{
- data->blit_mode->blit_func (data, src_x, src_y, dst_x, dst_y, width, height);
-}
-
-void
-_cogl_blit_end (CoglBlitData *data)
-{
- data->blit_mode->end_func (data);
-}