Пример #1
0
void
_cogl_texture_gl_maybe_update_max_level (CoglTexture *texture,
                                         int max_level)
{
  /* This isn't supported on GLES */
#ifdef HAVE_COGL_GL
  CoglContext *ctx = texture->context;

  if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL) &&
      texture->max_level < max_level)
    {
      CoglContext *ctx = texture->context;
      GLuint gl_handle;
      GLenum gl_target;

      cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);

      texture->max_level = max_level;

      _cogl_bind_gl_texture_transient (gl_target,
                                       gl_handle,
                                       _cogl_texture_is_foreign (texture));

      GE( ctx, glTexParameteri (gl_target,
                                GL_TEXTURE_MAX_LEVEL, texture->max_level));
    }
#endif /* HAVE_COGL_GL */
}
Пример #2
0
static CoglBool
_cogl_sub_texture_get_gl_texture (CoglTexture *tex,
                                  GLuint *out_gl_handle,
                                  GLenum *out_gl_target)
{
  CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);

  return cogl_texture_get_gl_texture (sub_tex->full_texture,
                                      out_gl_handle,
                                      out_gl_target);
}
Пример #3
0
static gboolean
_cogl_texture_pixmap_x11_get_gl_texture (CoglTexture *tex,
                                         GLuint      *out_gl_handle,
                                         GLenum      *out_gl_target)
{
  CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
  CoglTexture *child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);

  /* Forward on to the child texture */
  return cogl_texture_get_gl_texture (child_tex,
                                      out_gl_handle,
                                      out_gl_target);
}
Пример #4
0
void
_cogl_texture_gl_generate_mipmaps (CoglTexture *texture)
{
  CoglContext *ctx = texture->context;
  int n_levels = _cogl_texture_get_n_levels (texture);
  GLuint gl_handle;
  GLenum gl_target;

  _cogl_texture_gl_maybe_update_max_level (texture, n_levels - 1);

  cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);

  _cogl_bind_gl_texture_transient (gl_target,
                                   gl_handle,
                                   _cogl_texture_is_foreign (texture));
  GE( ctx, glGenerateMipmap (gl_target) );
}
static gboolean
texture_bind (ClutterGLXTexturePixmap *tex)
{
  GLuint     handle = 0;
  GLenum     target = 0;
  CoglHandle cogl_tex;
  cogl_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE(tex));

  if (!cogl_texture_get_gl_texture (cogl_tex, &handle, &target))
      return FALSE;

  glEnable(target);

  /* FIXME: fire off an error here? */
  glBindTexture (target, handle);

  return TRUE;
}
static CoglBool
_cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
                                             CoglTexture *texture,
                                             CoglBool is_foreign,
                                             int src_x,
                                             int src_y,
                                             int dst_x,
                                             int dst_y,
                                             int width,
                                             int height,
                                             int level,
                                             CoglBitmap *source_bmp,
				             GLuint source_gl_format,
				             GLuint source_gl_type,
                                             CoglError **error)
{
  GLenum gl_target;
  GLuint gl_handle;
  uint8_t *data;
  CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
  int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format);
  CoglBitmap *slice_bmp;
  int rowstride;
  GLenum gl_error;
  CoglBool status = TRUE;
  CoglError *internal_error = NULL;
  int level_width;
  int level_height;

  cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);

  /* If we have the GL_EXT_unpack_subimage extension then we can
     upload from subregions directly. Otherwise we may need to copy
     the bitmap */
  if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_UNPACK_SUBIMAGE) &&
      (src_x != 0 || src_y != 0 ||
       width != cogl_bitmap_get_width (source_bmp) ||
       height != cogl_bitmap_get_height (source_bmp)))
    {
      slice_bmp =
        _cogl_bitmap_new_with_malloc_buffer (ctx,
                                             width, height,
                                             source_format,
                                             error);
      if (!slice_bmp)
        return FALSE;

      if (!_cogl_bitmap_copy_subregion (source_bmp,
                                        slice_bmp,
                                        src_x, src_y,
                                        0, 0, /* dst_x/y */
                                        width, height,
                                        error))
        {
          cogl_object_unref (slice_bmp);
          return FALSE;
        }

      src_x = src_y = 0;
    }
  else
    {
      slice_bmp = prepare_bitmap_alignment_for_upload (ctx, source_bmp, error);
      if (!slice_bmp)
        return FALSE;
    }

  rowstride = cogl_bitmap_get_rowstride (slice_bmp);

  /* Setup gl alignment to match rowstride and top-left corner */
  prep_gl_for_pixels_upload_full (ctx, rowstride, src_x, src_y, bpp);

  data = _cogl_bitmap_gl_bind (slice_bmp, COGL_BUFFER_ACCESS_READ, 0, &internal_error);

  /* NB: _cogl_bitmap_gl_bind() may return NULL when successfull so we
   * have to explicitly check the cogl error pointer to catch
   * problems... */
  if (internal_error)
    {
      _cogl_propagate_error (error, internal_error);
      cogl_object_unref (slice_bmp);
      return FALSE;
    }

  _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);

  /* Clear any GL errors */
  while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
    ;

  _cogl_texture_get_level_size (texture,
                                level,
                                &level_width,
                                &level_height,
                                NULL);

  if (level_width == width && level_height == height)
    {
      /* GL gets upset if you use glTexSubImage2D to define the
       * contents of a mipmap level so we make sure to use
       * glTexImage2D if we are uploading a full mipmap level.
       */
      ctx->glTexImage2D (gl_target,
                         level,
                         _cogl_texture_gl_get_format (texture),
                         width,
                         height,
                         0,
                         source_gl_format,
                         source_gl_type,
                         data);
    }
  else
    {
      /* GL gets upset if you use glTexSubImage2D to initialize the
       * contents of a mipmap level so if this is the first time
       * we've seen a request to upload to this level we call
       * glTexImage2D first to assert that the storage for this
       * level exists.
       */
      if (texture->max_level < level)
        {
          ctx->glTexImage2D (gl_target,
                             level,
                             _cogl_texture_gl_get_format (texture),
                             level_width,
                             level_height,
                             0,
                             source_gl_format,
                             source_gl_type,
                             NULL);
        }

      ctx->glTexSubImage2D (gl_target,
                            level,
                            dst_x, dst_y,
                            width, height,
                            source_gl_format,
                            source_gl_type,
                            data);
    }

  if (_cogl_gl_util_catch_out_of_memory (ctx, error))
    status = FALSE;

  _cogl_bitmap_gl_unbind (slice_bmp);

  cogl_object_unref (slice_bmp);

  return status;
}
Пример #7
0
Context::Context( ClutterActor * actor )
:
	unpack_flip_y( false ),
    unpack_premultiply_alpha( false ),
    unpack_colorspace_conversion( GL_BROWSER_DEFAULT_WEBGL ),
    have_depth( false ),
    have_stencil( false ),
    acquisitions( 0 ),
    texture( 0 ),
    texture_target( 0 ),
    framebuffer( 0 )
{
	g_assert( CLUTTER_IS_TEXTURE( actor ) );

	// Make sure we are in the clutter context

	context_op( SWITCH_TO_CLUTTER_CONTEXT );

	// Get the Clutter GL texture id and target

#ifdef CLUTTER_VERSION_1_10

    CoglTexture * th = COGL_TEXTURE( clutter_texture_get_cogl_texture( CLUTTER_TEXTURE( actor ) ) );

#else

    CoglHandle th = clutter_texture_get_cogl_texture( CLUTTER_TEXTURE( actor ) );

#endif

	if ( ! cogl_texture_get_gl_texture( th , & texture , & texture_target ) )
	{
		tpwarn( "FAILED TO GET GL TEXTURE HANDLE" );
	}

	// Now, create our context and switch to it

	context_op( CREATE_CONTEXT );

	context_op( SWITCH_TO_MY_CONTEXT );

	// Get the width and height of the actor

	gfloat width;
	gfloat height;

	clutter_actor_get_size( actor , & width , & height );

	// Try to create the frame buffer in different ways until one
	// succeeds (or all fail).

	const int try_flags[] =
	{

#if defined(CLUTTER_WINDOWING_GLX) || defined(CLUTTER_WINDOWING_OSX)

        FBO_TRY_DEPTH_STENCIL ,

#endif
        FBO_TRY_DEPTH | FBO_TRY_STENCIL ,
        FBO_TRY_DEPTH ,
        FBO_TRY_STENCIL ,
        0
	};

	for ( size_t i = 0; i < sizeof( try_flags ) / sizeof( int ); ++i )
	{
		if ( try_create_fbo( width , height , try_flags[ i ] ) )
		{
			break;
		}
	}

	if ( ! framebuffer )
	{
		tpwarn( "UNABLE TO CREATE FRAMEBUFFER" );
	}
	else
	{
		tplog2( "FRAMEBUFFER READY : DEPTH = %s : STENCIL = %s" , have_depth ? "YES" : "NO" , have_stencil ? "YES" : "NO" );
	}

    context_op( SWITCH_TO_CLUTTER_CONTEXT );
}
Пример #8
0
static gboolean
_cogl_texture_pixmap_x11_update_glx_texture (CoglTexturePixmapX11 *tex_pixmap,
                                             gboolean needs_mipmap)
{
  gboolean ret = TRUE;

  _COGL_GET_CONTEXT (ctx, FALSE);

  /* If we don't have a GLX pixmap then fallback */
  if (tex_pixmap->glx_pixmap == None)
    ret = FALSE;
  else
    {
      /* Lazily create a texture to hold the pixmap */
      if (tex_pixmap->glx_tex == COGL_INVALID_HANDLE)
        {
          CoglPixelFormat texture_format;

          texture_format = (tex_pixmap->depth >= 32 ?
                            COGL_PIXEL_FORMAT_RGBA_8888_PRE :
                            COGL_PIXEL_FORMAT_RGB_888);

          if (should_use_rectangle ())
            {
              tex_pixmap->glx_tex =
                _cogl_texture_rectangle_new_with_size (tex_pixmap->width,
                                                       tex_pixmap->height,
                                                       COGL_TEXTURE_NO_ATLAS,
                                                       texture_format);

              if (tex_pixmap->glx_tex)
                COGL_NOTE (TEXTURE_PIXMAP, "Created a texture rectangle for %p",
                           tex_pixmap);
              else
                {
                  COGL_NOTE (TEXTURE_PIXMAP, "Falling back for %p because a "
                             "texture rectangle could not be created",
                             tex_pixmap);
                  _cogl_texture_pixmap_x11_free_glx_pixmap (tex_pixmap);
                  ret = FALSE;
                }
            }
          else
            {
              tex_pixmap->glx_tex =
                _cogl_texture_2d_new_with_size (tex_pixmap->width,
                                                tex_pixmap->height,
                                                COGL_TEXTURE_NO_ATLAS,
                                                texture_format);

              if (tex_pixmap->glx_tex)
                COGL_NOTE (TEXTURE_PIXMAP, "Created a texture 2d for %p",
                           tex_pixmap);
              else
                {
                  COGL_NOTE (TEXTURE_PIXMAP, "Falling back for %p because a "
                             "texture 2d could not be created",
                             tex_pixmap);
                  _cogl_texture_pixmap_x11_free_glx_pixmap (tex_pixmap);
                  ret = FALSE;
                }
            }
        }

      if (ret && needs_mipmap)
        {
          /* If we can't support mipmapping then temporarily fallback */
          if (!tex_pixmap->glx_can_mipmap)
            ret = FALSE;
          /* Recreate the GLXPixmap if it wasn't previously created with a
             mipmap tree */
          else if (!tex_pixmap->glx_pixmap_has_mipmap)
            {
              _cogl_texture_pixmap_x11_free_glx_pixmap (tex_pixmap);

              COGL_NOTE (TEXTURE_PIXMAP, "Recreating GLXPixmap with mipmap "
                         "support for %p", tex_pixmap);
              try_create_glx_pixmap (tex_pixmap, TRUE);

              /* If the pixmap failed then we'll permanently fallback to using
                 XImage. This shouldn't happen */
              if (tex_pixmap->glx_pixmap == None)
                {
                  COGL_NOTE (TEXTURE_PIXMAP, "Falling back to XGetImage "
                             "updates for %p because creating the GLXPixmap "
                             "with mipmap support failed", tex_pixmap);

                  if (tex_pixmap->glx_tex)
                    cogl_handle_unref (tex_pixmap->glx_tex);

                  ret = FALSE;
                }
              else
                tex_pixmap->bind_tex_image_queued = TRUE;
            }
        }

      if (ret && tex_pixmap->bind_tex_image_queued)
        {
          GLuint gl_handle, gl_target;

          cogl_texture_get_gl_texture (tex_pixmap->glx_tex,
                                       &gl_handle, &gl_target);

          COGL_NOTE (TEXTURE_PIXMAP, "Rebinding GLXPixmap for %p", tex_pixmap);

          GE( _cogl_bind_gl_texture_transient (gl_target, gl_handle, FALSE) );

          if (tex_pixmap->pixmap_bound)
            glXReleaseTexImage (_cogl_xlib_get_display (),
                                tex_pixmap->glx_pixmap,
                                GLX_FRONT_LEFT_EXT);

          glXBindTexImage (_cogl_xlib_get_display (),
                           tex_pixmap->glx_pixmap,
                           GLX_FRONT_LEFT_EXT,
                           NULL);

          /* According to the recommended usage in the spec for
             GLX_EXT_texture_pixmap we should release the texture after
             we've finished drawing with it and it is undefined what
             happens if you render to a pixmap that is bound to a
             texture. However that would require the texture backend to
             know when Cogl has finished painting and it may be more
             expensive to keep unbinding the texture. Leaving it bound
             appears to work on Mesa and NVidia drivers and it is also
             what Compiz does so it is probably ok */

          tex_pixmap->bind_tex_image_queued = FALSE;
          tex_pixmap->pixmap_bound = TRUE;

          _cogl_texture_2d_externally_modified (tex_pixmap->glx_tex);
        }
    }

  return ret;
}