예제 #1
0
void
_cogl_texture_driver_gen (GLenum   gl_target,
                          GLsizei  n,
                          GLuint  *textures)
{
    unsigned int i;

    GE (glGenTextures (n, textures));

    for (i = 0; i < n; i++)
    {
        _cogl_bind_gl_texture_transient (gl_target, textures[i], FALSE);

        switch (gl_target)
        {
        case GL_TEXTURE_2D:
        case GL_TEXTURE_3D:
            /* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
            GE( glTexParameteri (gl_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
            break;

        default:
            g_assert_not_reached();
        }
    }
}
예제 #2
0
void
_cogl_texture_2d_gl_copy_from_framebuffer (CoglTexture2D *tex_2d,
                                           int src_x,
                                           int src_y,
                                           int width,
                                           int height,
                                           CoglFramebuffer *src_fb,
                                           int dst_x,
                                           int dst_y,
                                           int level)
{
  CoglTexture *tex = COGL_TEXTURE (tex_2d);
  CoglContext *ctx = tex->context;

  /* Make sure the current framebuffers are bound, though we don't need to
   * flush the clip state here since we aren't going to draw to the
   * framebuffer. */
  _cogl_framebuffer_flush_state (ctx->current_draw_buffer,
                                 src_fb,
                                 COGL_FRAMEBUFFER_STATE_ALL &
                                 ~COGL_FRAMEBUFFER_STATE_CLIP);

  _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
                                   tex_2d->gl_texture,
                                   tex_2d->is_foreign);

  ctx->glCopyTexSubImage2D (GL_TEXTURE_2D,
                            0, /* level */
                            dst_x, dst_y,
                            src_x, src_y,
                            width, height);
}
예제 #3
0
void
_cogl_texture_2d_gl_generate_mipmap (CoglTexture2D *tex_2d)
{
  CoglContext *ctx = COGL_TEXTURE (tex_2d)->context;

  /* glGenerateMipmap is defined in the FBO extension. If it's not
     available we'll fallback to temporarily enabling
     GL_GENERATE_MIPMAP and reuploading the first pixel */
  if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
    _cogl_texture_gl_generate_mipmaps (COGL_TEXTURE (tex_2d));
#ifdef HAVE_COGL_GL
  else
    {
      _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
                                       tex_2d->gl_texture,
                                       tex_2d->is_foreign);

      GE( ctx, glTexParameteri (GL_TEXTURE_2D,
                                GL_GENERATE_MIPMAP,
                                GL_TRUE) );
      GE( ctx, glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, 1, 1,
                                tex_2d->first_pixel.gl_format,
                                tex_2d->first_pixel.gl_type,
                                tex_2d->first_pixel.data) );
      GE( ctx, glTexParameteri (GL_TEXTURE_2D,
                                GL_GENERATE_MIPMAP,
                                GL_FALSE) );
    }
#endif
}
예제 #4
0
파일: cogl-texture-gl.c 프로젝트: rib/cogl
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 */
}
예제 #5
0
void
_cogl_texture_2d_gl_get_data (CoglTexture2D *tex_2d,
                              CoglPixelFormat format,
                              int rowstride,
                              uint8_t *data)
{
  CoglContext *ctx = COGL_TEXTURE (tex_2d)->context;
  int bpp;
  int width = COGL_TEXTURE (tex_2d)->width;
  GLenum gl_format;
  GLenum gl_type;

  bpp = _cogl_pixel_format_get_bytes_per_pixel (format);

  ctx->driver_vtable->pixel_format_to_gl (ctx,
                                          format,
                                          NULL, /* internal format */
                                          &gl_format,
                                          &gl_type);

  ctx->texture_driver->prep_gl_for_pixels_download (ctx,
                                                    rowstride,
                                                    width,
                                                    bpp);

  _cogl_bind_gl_texture_transient (tex_2d->gl_target,
                                   tex_2d->gl_texture,
                                   tex_2d->is_foreign);

  ctx->texture_driver->gl_get_tex_image (ctx,
                                         tex_2d->gl_target,
                                         gl_format,
                                         gl_type,
                                         data);
}
예제 #6
0
static void
_cogl_texture_rectangle_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
                                                           GLenum wrap_mode_s,
                                                           GLenum wrap_mode_t,
                                                           GLenum wrap_mode_p)
{
  CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
  CoglContext *ctx = tex->context;

  /* Only set the wrap mode if it's different from the current value
     to avoid too many GL calls. Texture rectangle doesn't make use of
     the r coordinate so we can ignore its wrap mode */
  if (tex_rect->gl_legacy_texobj_wrap_mode_s != wrap_mode_s ||
      tex_rect->gl_legacy_texobj_wrap_mode_t != wrap_mode_t)
    {
      g_assert (can_use_wrap_mode (wrap_mode_s));
      g_assert (can_use_wrap_mode (wrap_mode_t));

      _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
                                       tex_rect->gl_texture,
                                       tex_rect->is_foreign);
      GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB,
                                GL_TEXTURE_WRAP_S, wrap_mode_s) );
      GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB,
                                GL_TEXTURE_WRAP_T, wrap_mode_t) );

      tex_rect->gl_legacy_texobj_wrap_mode_s = wrap_mode_s;
      tex_rect->gl_legacy_texobj_wrap_mode_t = wrap_mode_t;
    }
}
예제 #7
0
static void
_cogl_texture_driver_upload_to_gl (CoglContext *ctx,
                                   GLenum       gl_target,
                                   GLuint       gl_handle,
                                   CoglBool     is_foreign,
                                   CoglBitmap  *source_bmp,
                                   GLint        internal_gl_format,
                                   GLuint       source_gl_format,
                                   GLuint       source_gl_type)
{
  uint8_t *data;
  CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
  int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format);

  data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);

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

  _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);

  GE( ctx, glTexImage2D (gl_target, 0,
                         internal_gl_format,
                         cogl_bitmap_get_width (source_bmp),
                         cogl_bitmap_get_height (source_bmp),
                         0,
                         source_gl_format,
                         source_gl_type,
                         data) );

  _cogl_bitmap_unbind (source_bmp);
}
예제 #8
0
static CoglBool
_cogl_texture_rectangle_get_data (CoglTexture *tex,
                                  CoglPixelFormat format,
                                  int rowstride,
                                  uint8_t *data)
{
  CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
  CoglContext *ctx = tex->context;
  int bpp;
  GLenum gl_format;
  GLenum gl_type;

  bpp = _cogl_pixel_format_get_bytes_per_pixel (format);

  ctx->driver_vtable->pixel_format_to_gl (ctx,
                                          format,
                                          NULL, /* internal format */
                                          &gl_format,
                                          &gl_type);

  ctx->texture_driver->prep_gl_for_pixels_download (ctx,
                                                    rowstride,
                                                    tex->width,
                                                    bpp);

  _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
                                   tex_rect->gl_texture,
                                   tex_rect->is_foreign);
  return ctx->texture_driver->gl_get_tex_image (ctx,
                                                GL_TEXTURE_RECTANGLE_ARB,
                                                gl_format,
                                                gl_type,
                                                data);
}
예제 #9
0
static void
_cogl_texture_rectangle_gl_flush_legacy_texobj_filters (CoglTexture *tex,
                                                        GLenum min_filter,
                                                        GLenum mag_filter)
{
  CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
  CoglContext *ctx = tex->context;

  if (min_filter == tex_rect->gl_legacy_texobj_min_filter
      && mag_filter == tex_rect->gl_legacy_texobj_mag_filter)
    return;

  /* Rectangle textures don't support mipmapping */
  g_assert (min_filter == GL_LINEAR || min_filter == GL_NEAREST);

  /* Store new values */
  tex_rect->gl_legacy_texobj_min_filter = min_filter;
  tex_rect->gl_legacy_texobj_mag_filter = mag_filter;

  /* Apply new filters to the texture */
  _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
                                   tex_rect->gl_texture,
                                   tex_rect->is_foreign);
  GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
                            mag_filter) );
  GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
                            min_filter) );
}
static GLuint
_cogl_texture_driver_gen (CoglContext *ctx,
                          GLenum gl_target,
                          CoglPixelFormat internal_format)
{
  GLuint tex;

  GE (ctx, glGenTextures (1, &tex));

  _cogl_bind_gl_texture_transient (gl_target, tex, FALSE);

  switch (gl_target)
    {
    case GL_TEXTURE_2D:
    case GL_TEXTURE_3D:
      /* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
      GE( ctx, glTexParameteri (gl_target,
                                GL_TEXTURE_MIN_FILTER,
                                GL_LINEAR) );
      break;

    default:
      g_assert_not_reached();
    }

  return tex;
}
예제 #11
0
void
_cogl_texture_2d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
                                                    GLenum wrap_mode_s,
                                                    GLenum wrap_mode_t,
                                                    GLenum wrap_mode_p)
{
  CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
  CoglContext *ctx = tex->context;

  /* Only set the wrap mode if it's different from the current value
     to avoid too many GL calls. Texture 2D doesn't make use of the r
     coordinate so we can ignore its wrap mode */
  if (tex_2d->gl_legacy_texobj_wrap_mode_s != wrap_mode_s ||
      tex_2d->gl_legacy_texobj_wrap_mode_t != wrap_mode_t)
    {
      _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
                                       tex_2d->gl_texture,
                                       tex_2d->is_foreign);
      GE( ctx, glTexParameteri (GL_TEXTURE_2D,
                                GL_TEXTURE_WRAP_S,
                                wrap_mode_s) );
      GE( ctx, glTexParameteri (GL_TEXTURE_2D,
                                GL_TEXTURE_WRAP_T,
                                wrap_mode_t) );

      tex_2d->gl_legacy_texobj_wrap_mode_s = wrap_mode_s;
      tex_2d->gl_legacy_texobj_wrap_mode_t = wrap_mode_t;
    }
}
예제 #12
0
static void
_cogl_texture_3d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
                                                    GLenum wrap_mode_s,
                                                    GLenum wrap_mode_t,
                                                    GLenum wrap_mode_p)
{
  CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
  CoglContext *ctx = tex->context;

  /* Only set the wrap mode if it's different from the current value
     to avoid too many GL calls. */
  if (tex_3d->gl_legacy_texobj_wrap_mode_s != wrap_mode_s ||
      tex_3d->gl_legacy_texobj_wrap_mode_t != wrap_mode_t ||
      tex_3d->gl_legacy_texobj_wrap_mode_p != wrap_mode_p)
    {
      _cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
                                       tex_3d->gl_texture,
                                       FALSE);
      GE( ctx, glTexParameteri (GL_TEXTURE_3D,
                                GL_TEXTURE_WRAP_S,
                                wrap_mode_s) );
      GE( ctx, glTexParameteri (GL_TEXTURE_3D,
                                GL_TEXTURE_WRAP_T,
                                wrap_mode_t) );
      GE( ctx, glTexParameteri (GL_TEXTURE_3D,
                                GL_TEXTURE_WRAP_R,
                                wrap_mode_p) );

      tex_3d->gl_legacy_texobj_wrap_mode_s = wrap_mode_s;
      tex_3d->gl_legacy_texobj_wrap_mode_t = wrap_mode_t;
      tex_3d->gl_legacy_texobj_wrap_mode_p = wrap_mode_p;
    }
}
예제 #13
0
파일: cogl-texture-gl.c 프로젝트: rib/cogl
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) );
}
예제 #14
0
static void
_cogl_texture_3d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
{
  CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
  CoglContext *ctx = tex->context;

  /* Only update if the mipmaps are dirty */
  if ((flags & COGL_TEXTURE_NEEDS_MIPMAP) &&
      tex_3d->auto_mipmap && tex_3d->mipmaps_dirty)
    {
      /* glGenerateMipmap is defined in the FBO extension. If it's not
         available we'll fallback to temporarily enabling
         GL_GENERATE_MIPMAP and reuploading the first pixel */
      if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
        _cogl_texture_gl_generate_mipmaps (tex);
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
      else if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED))
        {
          _cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
                                           tex_3d->gl_texture,
                                           FALSE);

          GE( ctx, glTexParameteri (GL_TEXTURE_3D,
                                    GL_GENERATE_MIPMAP,
                                    GL_TRUE) );
          GE( ctx, glTexSubImage3D (GL_TEXTURE_3D,
                                    0, /* level */
                                    0, /* xoffset */
                                    0, /* yoffset */
                                    0, /* zoffset */
                                    1, /* width */
                                    1, /* height */
                                    1, /* depth */
                                    tex_3d->first_pixel.gl_format,
                                    tex_3d->first_pixel.gl_type,
                                    tex_3d->first_pixel.data) );
          GE( ctx, glTexParameteri (GL_TEXTURE_3D,
                                    GL_GENERATE_MIPMAP,
                                    GL_FALSE) );
        }
#endif

      tex_3d->mipmaps_dirty = FALSE;
    }
}
예제 #15
0
void
_cogl_texture_driver_upload_to_gl (GLenum       gl_target,
                                   GLuint       gl_handle,
                                   gboolean     is_foreign,
                                   CoglBitmap  *source_bmp,
                                   GLint        internal_gl_format,
                                   GLuint       source_gl_format,
                                   GLuint       source_gl_type)
{
    int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
    int rowstride;
    int bmp_width = _cogl_bitmap_get_width (source_bmp);
    int bmp_height = _cogl_bitmap_get_height (source_bmp);
    CoglBitmap *bmp;
    guint8 *data;

    bmp = prepare_bitmap_alignment_for_upload (source_bmp);
    rowstride = _cogl_bitmap_get_rowstride (bmp);

    /* Setup gl alignment to match rowstride and top-left corner */
    _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);

    _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);

    data = _cogl_bitmap_bind (bmp, COGL_BUFFER_ACCESS_READ, 0);

    GE( glTexImage2D (gl_target, 0,
                      internal_gl_format,
                      bmp_width, bmp_height,
                      0,
                      source_gl_format,
                      source_gl_type,
                      data) );

    _cogl_bitmap_unbind (bmp);

    cogl_object_unref (bmp);
}
예제 #16
0
static void
_cogl_texture_3d_gl_flush_legacy_texobj_filters (CoglTexture *tex,
                                                 GLenum min_filter,
                                                 GLenum mag_filter)
{
  CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
  CoglContext *ctx = tex->context;

  if (min_filter == tex_3d->gl_legacy_texobj_min_filter
      && mag_filter == tex_3d->gl_legacy_texobj_mag_filter)
    return;

  /* Store new values */
  tex_3d->gl_legacy_texobj_min_filter = min_filter;
  tex_3d->gl_legacy_texobj_mag_filter = mag_filter;

  /* Apply new filters to the texture */
  _cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
                                   tex_3d->gl_texture,
                                   FALSE);
  GE( ctx, glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, mag_filter) );
  GE( ctx, glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, min_filter) );
}
예제 #17
0
static gboolean
allocate_from_egl_image (CoglTexture2D *tex_2d,
                         CoglTextureLoader *loader,
                         CoglError **error)
{
  CoglTexture *tex = COGL_TEXTURE (tex_2d);
  CoglContext *ctx = tex->context;
  CoglPixelFormat internal_format = loader->src.egl_image.format;

  tex_2d->gl_texture =
    ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, internal_format);
  _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
                                   tex_2d->gl_texture,
                                   FALSE);
  _cogl_gl_util_clear_gl_errors (ctx);

  ctx->glEGLImageTargetTexture2D (GL_TEXTURE_2D, loader->src.egl_image.image);
  if (_cogl_gl_util_get_error (ctx) != GL_NO_ERROR)
    {
      _cogl_set_error (error,
                       COGL_TEXTURE_ERROR,
                       COGL_TEXTURE_ERROR_BAD_PARAMETER,
                       "Could not create a CoglTexture2D from a given "
                       "EGLImage");
      GE( ctx, glDeleteTextures (1, &tex_2d->gl_texture) );
      return FALSE;
    }

  tex_2d->internal_format = internal_format;

  _cogl_texture_set_allocated (tex,
                               internal_format,
                               loader->src.egl_image.width,
                               loader->src.egl_image.height);

  return TRUE;
}
예제 #18
0
static void
_cogl_texture_driver_gen (CoglContext *ctx,
                          GLenum gl_target,
                          GLsizei n,
                          GLuint *textures)
{
  unsigned int i;

  GE (ctx, glGenTextures (n, textures));

  for (i = 0; i < n; i++)
    {
      _cogl_bind_gl_texture_transient (gl_target,
                                       textures[i],
                                       FALSE);

      switch (gl_target)
        {
        case GL_TEXTURE_2D:
        case GL_TEXTURE_3D:
          /* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
          GE( ctx, glTexParameteri (gl_target,
                                    GL_TEXTURE_MIN_FILTER,
                                    GL_LINEAR) );
          break;

        case GL_TEXTURE_RECTANGLE_ARB:
          /* Texture rectangles already default to GL_LINEAR so nothing
             needs to be done */
          break;

        default:
          g_assert_not_reached();
        }
    }
}
예제 #19
0
static CoglBool
allocate_with_size (CoglTexture3D *tex_3d,
                    CoglTextureLoader *loader,
                    CoglError **error)
{
  CoglTexture *tex = COGL_TEXTURE (tex_3d);
  CoglContext *ctx = tex->context;
  CoglPixelFormat internal_format;
  int width = loader->src.sized.width;
  int height = loader->src.sized.height;
  int depth = loader->src.sized.depth;
  GLenum gl_intformat;
  GLenum gl_format;
  GLenum gl_type;
  GLenum gl_texture;

  internal_format =
    _cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY);

  if (!_cogl_texture_3d_can_create (ctx,
                                    width,
                                    height,
                                    depth,
                                    internal_format,
                                    error))
    return FALSE;

  ctx->driver_vtable->pixel_format_to_gl (ctx,
                                          internal_format,
                                          &gl_intformat,
                                          &gl_format,
                                          &gl_type);

  gl_texture =
    ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, internal_format);
  _cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
                                   gl_texture,
                                   FALSE);
  /* Clear any GL errors */
  _cogl_gl_util_clear_gl_errors (ctx);

  ctx->glTexImage3D (GL_TEXTURE_3D, 0, gl_intformat,
                     width, height, depth,
                     0, gl_format, gl_type, NULL);

  if (_cogl_gl_util_catch_out_of_memory (ctx, error))
    {
      GE( ctx, glDeleteTextures (1, &gl_texture) );
      return FALSE;
    }

  tex_3d->gl_texture = gl_texture;
  tex_3d->gl_format = gl_intformat;

  tex_3d->depth = depth;

  tex_3d->internal_format = internal_format;

  _cogl_texture_set_allocated (tex, internal_format, width, height);

  return TRUE;
}
예제 #20
0
static CoglBool
allocate_from_gl_foreign (CoglTextureRectangle *tex_rect,
                          CoglTextureLoader *loader,
                          CoglError **error)
{
  CoglTexture *tex = COGL_TEXTURE (tex_rect);
  CoglContext *ctx = tex->context;
  CoglPixelFormat format = loader->src.gl_foreign.format;
  GLenum gl_error = 0;
  GLint gl_compressed = GL_FALSE;
  GLenum gl_int_format = 0;

  if (!ctx->texture_driver->allows_foreign_gl_target (ctx,
                                                      GL_TEXTURE_RECTANGLE_ARB))
    {
      _cogl_set_error (error,
                       COGL_SYSTEM_ERROR,
                       COGL_SYSTEM_ERROR_UNSUPPORTED,
                       "Foreign GL_TEXTURE_RECTANGLE textures are not "
                       "supported by your system");
      return FALSE;
    }

  /* Make sure binding succeeds */
  while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
    ;

  _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
                                   loader->src.gl_foreign.gl_handle, TRUE);
  if (ctx->glGetError () != GL_NO_ERROR)
    {
      _cogl_set_error (error,
                       COGL_SYSTEM_ERROR,
                       COGL_SYSTEM_ERROR_UNSUPPORTED,
                       "Failed to bind foreign GL_TEXTURE_RECTANGLE texture");
      return FALSE;
    }

  /* Obtain texture parameters */

#ifdef HAVE_COGL_GL
  if (_cogl_has_private_feature
      (ctx, COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS))
    {
      GLint val;

      GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0,
                                         GL_TEXTURE_COMPRESSED,
                                         &gl_compressed) );

      GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0,
                                         GL_TEXTURE_INTERNAL_FORMAT,
                                         &val) );

      gl_int_format = val;

      /* If we can query GL for the actual pixel format then we'll ignore
         the passed in format and use that. */
      if (!ctx->driver_vtable->pixel_format_from_gl_internal (ctx,
                                                              gl_int_format,
                                                              &format))
        {
          _cogl_set_error (error,
                           COGL_SYSTEM_ERROR,
                           COGL_SYSTEM_ERROR_UNSUPPORTED,
                           "Unsupported internal format for foreign texture");
          return FALSE;
        }
    }
  else
#endif
    {
      /* Otherwise we'll assume we can derive the GL format from the
         passed in format */
      ctx->driver_vtable->pixel_format_to_gl (ctx,
                                              format,
                                              &gl_int_format,
                                              NULL,
                                              NULL);
    }

  /* Compressed texture images not supported */
  if (gl_compressed == GL_TRUE)
    {
      _cogl_set_error (error,
                       COGL_SYSTEM_ERROR,
                       COGL_SYSTEM_ERROR_UNSUPPORTED,
                       "Compressed foreign textures aren't currently supported");
      return FALSE;
    }

  /* Setup bitmap info */
  tex_rect->is_foreign = TRUE;

  tex_rect->gl_texture = loader->src.gl_foreign.gl_handle;
  tex_rect->gl_format = gl_int_format;

  /* Unknown filter */
  tex_rect->gl_legacy_texobj_min_filter = GL_FALSE;
  tex_rect->gl_legacy_texobj_mag_filter = GL_FALSE;

  tex_rect->internal_format = format;

  _cogl_texture_set_allocated (COGL_TEXTURE (tex_rect),
                               format,
                               loader->src.gl_foreign.width,
                               loader->src.gl_foreign.height);

  return TRUE;
}
static CoglBool
_cogl_texture_driver_upload_to_gl_3d (CoglContext *ctx,
                                      GLenum gl_target,
                                      GLuint gl_handle,
                                      CoglBool is_foreign,
                                      GLint height,
                                      GLint depth,
                                      CoglBitmap *source_bmp,
                                      GLint internal_gl_format,
                                      GLuint source_gl_format,
                                      GLuint source_gl_type,
                                      CoglError **error)
{
  CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
  int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format);
  int rowstride = cogl_bitmap_get_rowstride (source_bmp);
  int bmp_width = cogl_bitmap_get_width (source_bmp);
  int bmp_height = cogl_bitmap_get_height (source_bmp);
  uint8_t *data;
  GLenum gl_error;

  _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);

  /* If the rowstride or image height can't be specified with just
     GL_ALIGNMENT alone then we need to copy the bitmap because there
     is no GL_ROW_LENGTH */
  if (rowstride / bpp != bmp_width ||
      height != bmp_height / depth)
    {
      CoglBitmap *bmp;
      int image_height = bmp_height / depth;
      CoglPixelFormat source_bmp_format = cogl_bitmap_get_format (source_bmp);
      int i;

      _cogl_texture_driver_prep_gl_for_pixels_upload (ctx, bmp_width * bpp, bpp);

      /* Initialize the texture with empty data and then upload each
         image with a sub-region update */

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

      ctx->glTexImage3D (gl_target,
                         0, /* level */
                         internal_gl_format,
                         bmp_width,
                         height,
                         depth,
                         0,
                         source_gl_format,
                         source_gl_type,
                         NULL);

      if (_cogl_gl_util_catch_out_of_memory (ctx, error))
        return FALSE;

      bmp = _cogl_bitmap_new_with_malloc_buffer (ctx,
                                                 bmp_width,
                                                 height,
                                                 source_bmp_format,
                                                 error);
      if (!bmp)
        return FALSE;

      for (i = 0; i < depth; i++)
        {
          if (!_cogl_bitmap_copy_subregion (source_bmp,
                                            bmp,
                                            0, image_height * i,
                                            0, 0,
                                            bmp_width,
                                            height,
                                            error))
            {
              cogl_object_unref (bmp);
              return FALSE;
            }

          data = _cogl_bitmap_gl_bind (bmp,
                                       COGL_BUFFER_ACCESS_READ, 0, error);
          if (!data)
            {
              cogl_object_unref (bmp);
              return FALSE;
            }

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

          ctx->glTexSubImage3D (gl_target,
                                0, /* level */
                                0, /* xoffset */
                                0, /* yoffset */
                                i, /* zoffset */
                                bmp_width, /* width */
                                height, /* height */
                                1, /* depth */
                                source_gl_format,
                                source_gl_type,
                                data);

          if (_cogl_gl_util_catch_out_of_memory (ctx, error))
            {
              cogl_object_unref (bmp);
              _cogl_bitmap_gl_unbind (bmp);
              return FALSE;
            }

          _cogl_bitmap_gl_unbind (bmp);
        }

      cogl_object_unref (bmp);
    }
  else
    {
      data = _cogl_bitmap_gl_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0, error);
      if (!data)
        return FALSE;

      _cogl_texture_driver_prep_gl_for_pixels_upload (ctx, rowstride, bpp);

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

      ctx->glTexImage3D (gl_target,
                         0, /* level */
                         internal_gl_format,
                         bmp_width,
                         height,
                         depth,
                         0,
                         source_gl_format,
                         source_gl_type,
                         data);

      if (_cogl_gl_util_catch_out_of_memory (ctx, error))
        {
          _cogl_bitmap_gl_unbind (source_bmp);
          return FALSE;
        }

      _cogl_bitmap_gl_unbind (source_bmp);
    }

  return TRUE;
}
static CoglBool
_cogl_texture_driver_upload_to_gl (CoglContext *ctx,
                                   GLenum gl_target,
                                   GLuint gl_handle,
                                   CoglBool is_foreign,
                                   CoglBitmap *source_bmp,
                                   GLint internal_gl_format,
                                   GLuint source_gl_format,
                                   GLuint source_gl_type,
                                   CoglError **error)
{
  CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
  int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format);
  int rowstride;
  int bmp_width = cogl_bitmap_get_width (source_bmp);
  int bmp_height = cogl_bitmap_get_height (source_bmp);
  CoglBitmap *bmp;
  uint8_t *data;
  GLenum gl_error;
  CoglError *internal_error = NULL;
  CoglBool status = TRUE;

  bmp = prepare_bitmap_alignment_for_upload (ctx, source_bmp, error);
  if (!bmp)
    return FALSE;

  rowstride = cogl_bitmap_get_rowstride (bmp);

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

  _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);

  data = _cogl_bitmap_gl_bind (bmp,
                               COGL_BUFFER_ACCESS_READ,
                               0, /* hints */
                               &internal_error);

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

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

  ctx->glTexImage2D (gl_target, 0,
                     internal_gl_format,
                     bmp_width, bmp_height,
                     0,
                     source_gl_format,
                     source_gl_type,
                     data);

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

  _cogl_bitmap_gl_unbind (bmp);

  cogl_object_unref (bmp);

  return status;
}
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;
}
예제 #24
0
void
_cogl_texture_driver_upload_subregion_to_gl (GLenum       gl_target,
        GLuint       gl_handle,
        gboolean     is_foreign,
        int          src_x,
        int          src_y,
        int          dst_x,
        int          dst_y,
        int          width,
        int          height,
        CoglBitmap  *source_bmp,
        GLuint       source_gl_format,
        GLuint       source_gl_type)
{
    guint8 *data;
    CoglPixelFormat source_format = _cogl_bitmap_get_format (source_bmp);
    int bpp = _cogl_get_format_bpp (source_format);
    CoglBitmap *slice_bmp;
    int rowstride;

    /* If we are copying a sub region of the source bitmap then we need
       to copy it because GLES does not support GL_UNPACK_ROW_LENGTH */
    if (src_x != 0 || src_y != 0 ||
            width != _cogl_bitmap_get_width (source_bmp) ||
            height != _cogl_bitmap_get_height (source_bmp))
    {
        rowstride = bpp * width;
        rowstride = (rowstride + 3) & ~3;
        slice_bmp =
            _cogl_bitmap_new_from_data (g_malloc (height * rowstride),
                                        source_format,
                                        width, height,
                                        rowstride,
                                        (CoglBitmapDestroyNotify) g_free,
                                        NULL);
        _cogl_bitmap_copy_subregion (source_bmp,
                                     slice_bmp,
                                     src_x, src_y,
                                     0, 0, /* dst_x/y */
                                     width, height);
    }
    else
    {
        slice_bmp = prepare_bitmap_alignment_for_upload (source_bmp);
        rowstride = _cogl_bitmap_get_rowstride (slice_bmp);
    }

    /* Setup gl alignment to match rowstride and top-left corner */
    _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);

    data = _cogl_bitmap_bind (slice_bmp, COGL_BUFFER_ACCESS_READ, 0);

    _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);

    GE( glTexSubImage2D (gl_target, 0,
                         dst_x, dst_y,
                         width, height,
                         source_gl_format,
                         source_gl_type,
                         data) );

    _cogl_bitmap_unbind (slice_bmp);

    cogl_object_unref (slice_bmp);
}
예제 #25
0
void
_cogl_texture_driver_upload_to_gl_3d (GLenum       gl_target,
                                      GLuint       gl_handle,
                                      gboolean     is_foreign,
                                      GLint        height,
                                      GLint        depth,
                                      CoglBitmap  *source_bmp,
                                      GLint        internal_gl_format,
                                      GLuint       source_gl_format,
                                      GLuint       source_gl_type)
{
    int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
    int rowstride = _cogl_bitmap_get_rowstride (source_bmp);
    int bmp_width = _cogl_bitmap_get_width (source_bmp);
    int bmp_height = _cogl_bitmap_get_height (source_bmp);
    guint8 *data;

    _COGL_GET_CONTEXT (ctx, NO_RETVAL);

    _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);

    /* If the rowstride or image height can't be specified with just
       GL_ALIGNMENT alone then we need to copy the bitmap because there
       is no GL_ROW_LENGTH */
    if (rowstride / bpp != bmp_width ||
            height != bmp_height / depth)
    {
        CoglBitmap *bmp;
        int image_height = bmp_height / depth;
        int i;

        _cogl_texture_driver_prep_gl_for_pixels_upload (bmp_width * bpp, bpp);

        /* Initialize the texture with empty data and then upload each
           image with a sub-region update */

        GE( glTexImage3D (gl_target,
                          0, /* level */
                          internal_gl_format,
                          bmp_width,
                          height,
                          depth,
                          0,
                          source_gl_format,
                          source_gl_type,
                          NULL) );

        bmp = _cogl_bitmap_new_from_data (g_malloc (bpp * bmp_width * height),
                                          _cogl_bitmap_get_format (source_bmp),
                                          bmp_width,
                                          height,
                                          bpp * bmp_width,
                                          (CoglBitmapDestroyNotify) g_free,
                                          NULL);

        for (i = 0; i < depth; i++)
        {
            _cogl_bitmap_copy_subregion (source_bmp,
                                         bmp,
                                         0, image_height * i,
                                         0, 0,
                                         bmp_width,
                                         height);

            data = _cogl_bitmap_bind (bmp,
                                      COGL_BUFFER_ACCESS_READ, 0);

            GE( glTexSubImage3D (gl_target,
                                 0, /* level */
                                 0, /* xoffset */
                                 0, /* yoffset */
                                 i, /* zoffset */
                                 bmp_width, /* width */
                                 height, /* height */
                                 1, /* depth */
                                 source_gl_format,
                                 source_gl_type,
                                 data) );

            _cogl_bitmap_unbind (bmp);
        }

        cogl_object_unref (bmp);
    }
    else
    {
        data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);

        _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);

        GE( glTexImage3D (gl_target,
                          0, /* level */
                          internal_gl_format,
                          bmp_width,
                          height,
                          depth,
                          0,
                          source_gl_format,
                          source_gl_type,
                          data) );

        _cogl_bitmap_unbind (source_bmp);
    }
}
예제 #26
0
static gboolean
allocate_with_size (CoglTexture2D *tex_2d,
                    CoglTextureLoader *loader,
                    CoglError **error)
{
  CoglTexture *tex = COGL_TEXTURE (tex_2d);
  CoglPixelFormat internal_format;
  int width = loader->src.sized.width;
  int height = loader->src.sized.height;
  CoglContext *ctx = tex->context;
  GLenum gl_intformat;
  GLenum gl_format;
  GLenum gl_type;
  GLenum gl_texture;

  internal_format =
    _cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY);

  if (!_cogl_texture_2d_gl_can_create (ctx,
                                       width,
                                       height,
                                       internal_format))
    {
      _cogl_set_error (error, COGL_TEXTURE_ERROR,
                       COGL_TEXTURE_ERROR_SIZE,
                       "Failed to create texture 2d due to size/format"
                       " constraints");
      return FALSE;
    }

  ctx->driver_vtable->pixel_format_to_gl (ctx,
                                          internal_format,
                                          &gl_intformat,
                                          &gl_format,
                                          &gl_type);

  gl_texture = ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, internal_format);

  tex_2d->gl_internal_format = gl_intformat;

  _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
                                   gl_texture,
                                   tex_2d->is_foreign);

  /* Clear any GL errors */
  _cogl_gl_util_clear_gl_errors (ctx);

  ctx->glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat,
                     width, height, 0, gl_format, gl_type, NULL);

  if (_cogl_gl_util_catch_out_of_memory (ctx, error))
    {
      GE( ctx, glDeleteTextures (1, &gl_texture) );
      return FALSE;
    }

  tex_2d->gl_texture = gl_texture;
  tex_2d->gl_internal_format = gl_intformat;

  tex_2d->internal_format = internal_format;

  _cogl_texture_set_allocated (tex, internal_format, width, height);

  return TRUE;
}
예제 #27
0
static CoglBool
allocate_with_size (CoglTextureRectangle *tex_rect,
                    CoglTextureLoader *loader,
                    CoglError **error)
{
  CoglTexture *tex = COGL_TEXTURE (tex_rect);
  CoglContext *ctx = tex->context;
  CoglPixelFormat internal_format;
  int width = loader->src.sized.width;
  int height = loader->src.sized.height;
  GLenum gl_intformat;
  GLenum gl_format;
  GLenum gl_type;
  GLenum gl_error;
  GLenum gl_texture;

  internal_format =
    _cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY);

  if (!_cogl_texture_rectangle_can_create (ctx,
                                           width,
                                           height,
                                           internal_format,
                                           error))
    return FALSE;

  ctx->driver_vtable->pixel_format_to_gl (ctx,
                                          internal_format,
                                          &gl_intformat,
                                          &gl_format,
                                          &gl_type);

  gl_texture =
    ctx->texture_driver->gen (ctx,
                              GL_TEXTURE_RECTANGLE_ARB,
                              internal_format);
  _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
                                   gl_texture,
                                   tex_rect->is_foreign);

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

  ctx->glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, gl_intformat,
                     width, height, 0, gl_format, gl_type, NULL);

  if (_cogl_gl_util_catch_out_of_memory (ctx, error))
    {
      GE( ctx, glDeleteTextures (1, &gl_texture) );
      return FALSE;
    }

  tex_rect->internal_format = internal_format;

  tex_rect->gl_texture = gl_texture;
  tex_rect->gl_format = gl_intformat;

  _cogl_texture_set_allocated (COGL_TEXTURE (tex_rect),
                               internal_format, width, height);

  return TRUE;
}
예제 #28
0
static gboolean
allocate_from_gl_foreign (CoglTexture2D *tex_2d,
                          CoglTextureLoader *loader,
                          CoglError **error)
{
  CoglTexture *tex = COGL_TEXTURE (tex_2d);
  CoglContext *ctx = tex->context;
  CoglPixelFormat format = loader->src.gl_foreign.format;
  GLint gl_compressed = GL_FALSE;
  GLenum gl_int_format = 0;

  if (!ctx->texture_driver->allows_foreign_gl_target (ctx, GL_TEXTURE_2D))
    {
      _cogl_set_error (error,
                       COGL_SYSTEM_ERROR,
                       COGL_SYSTEM_ERROR_UNSUPPORTED,
                       "Foreign GL_TEXTURE_2D textures are not "
                       "supported by your system");
      return FALSE;
    }

  /* Make sure binding succeeds */
  _cogl_gl_util_clear_gl_errors (ctx);

  _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
                                   loader->src.gl_foreign.gl_handle, TRUE);
  if (_cogl_gl_util_get_error (ctx) != GL_NO_ERROR)
    {
      _cogl_set_error (error,
                       COGL_SYSTEM_ERROR,
                       COGL_SYSTEM_ERROR_UNSUPPORTED,
                       "Failed to bind foreign GL_TEXTURE_2D texture");
      return FALSE;
    }

  /* Obtain texture parameters
     (only level 0 we are interested in) */

#ifdef HAVE_COGL_GL
  if (_cogl_has_private_feature
      (ctx, COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS))
    {
      GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
                                         GL_TEXTURE_COMPRESSED,
                                         &gl_compressed) );

      {
        GLint val;

        GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
                                           GL_TEXTURE_INTERNAL_FORMAT,
                                           &val) );

        gl_int_format = val;
      }

      /* If we can query GL for the actual pixel format then we'll ignore
         the passed in format and use that. */
      if (!ctx->driver_vtable->pixel_format_from_gl_internal (ctx,
                                                              gl_int_format,
                                                              &format))
        {
          _cogl_set_error (error,
                           COGL_SYSTEM_ERROR,
                           COGL_SYSTEM_ERROR_UNSUPPORTED,
                           "Unsupported internal format for foreign texture");
          return FALSE;
        }
    }
  else
#endif
    {
      /* Otherwise we'll assume we can derive the GL format from the
         passed in format */
      ctx->driver_vtable->pixel_format_to_gl (ctx,
                                              format,
                                              &gl_int_format,
                                              NULL,
                                              NULL);
    }

  /* Compressed texture images not supported */
  if (gl_compressed == GL_TRUE)
    {
      _cogl_set_error (error,
                       COGL_SYSTEM_ERROR,
                       COGL_SYSTEM_ERROR_UNSUPPORTED,
                       "Compressed foreign textures aren't currently supported");
      return FALSE;
    }

  /* Note: previously this code would query the texture object for
     whether it has GL_GENERATE_MIPMAP enabled to determine whether to
     auto-generate the mipmap. This doesn't make much sense any more
     since Cogl switch to using glGenerateMipmap. Ideally I think
     cogl_texture_2d_gl_new_from_foreign should take a flags parameter so
     that the application can decide whether it wants
     auto-mipmapping. To be compatible with existing code, Cogl now
     disables its own auto-mipmapping but leaves the value of
     GL_GENERATE_MIPMAP alone so that it would still work but without
     the dirtiness tracking that Cogl would do. */

  _cogl_texture_2d_set_auto_mipmap (COGL_TEXTURE (tex_2d), FALSE);

  /* Setup bitmap info */
  tex_2d->is_foreign = TRUE;
  tex_2d->mipmaps_dirty = TRUE;

  tex_2d->gl_texture = loader->src.gl_foreign.gl_handle;
  tex_2d->gl_internal_format = gl_int_format;

  /* Unknown filter */
  tex_2d->gl_legacy_texobj_min_filter = GL_FALSE;
  tex_2d->gl_legacy_texobj_mag_filter = GL_FALSE;

  tex_2d->internal_format = format;

  _cogl_texture_set_allocated (tex,
                               format,
                               loader->src.gl_foreign.width,
                               loader->src.gl_foreign.height);
  return TRUE;
}
예제 #29
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;
}