CoglBitmap * _cogl_bitmap_from_file (const char *filename, GError **error) { static CoglUserDataKey bitmap_data_key; CoglBitmap *bmp; int stb_pixel_format; int width; int height; uint8_t *pixels; _COGL_GET_CONTEXT (ctx, NULL); _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, FALSE); /* Load from file using stb */ pixels = stbi_load (filename, &width, &height, &stb_pixel_format, STBI_rgb_alpha); if (pixels == NULL) return FALSE; /* Store bitmap info */ bmp = cogl_bitmap_new_for_data (ctx, width, height, COGL_PIXEL_FORMAT_RGBA_8888, width * 4, /* rowstride */ pixels); /* Register a destroy function so the pixel data will be freed automatically when the bitmap object is destroyed */ cogl_object_set_user_data (COGL_OBJECT (bmp), &bitmap_data_key, pixels, free); return bmp; }
CoglBitmap * _cogl_bitmap_new_with_malloc_buffer (CoglContext *context, unsigned int width, unsigned int height, CoglPixelFormat format, CoglError **error) { static CoglUserDataKey bitmap_free_key; int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); int rowstride = ((width * bpp) + 3) & ~3; uint8_t *data = g_try_malloc (rowstride * height); CoglBitmap *bitmap; if (!data) { _cogl_set_error (error, COGL_SYSTEM_ERROR, COGL_SYSTEM_ERROR_NO_MEMORY, "Failed to allocate memory for bitmap"); return NULL; } bitmap = cogl_bitmap_new_for_data (context, width, height, format, rowstride, data); cogl_object_set_user_data (COGL_OBJECT (bitmap), &bitmap_free_key, data, g_free); return bitmap; }
CoglXlibRenderer * _cogl_xlib_renderer_get_data (CoglRenderer *renderer) { static CoglUserDataKey key; CoglXlibRenderer *data; /* Constructs a CoglXlibRenderer struct on demand and attaches it to the object using user data. It's done this way instead of using a subclassing hierarchy in the winsys data because all EGL winsys's need the EGL winsys data but only one of them wants the Xlib data. */ data = cogl_object_get_user_data (COGL_OBJECT (renderer), &key); if (data == NULL) { data = g_slice_new0 (CoglXlibRenderer); cogl_object_set_user_data (COGL_OBJECT (renderer), &key, data, destroy_xlib_renderer_data); } return data; }
static void dirty_shader_state (CoglPipeline *pipeline) { cogl_object_set_user_data (COGL_OBJECT (pipeline), &shader_state_key, NULL, NULL); }
static void set_glsl_priv (CoglPipeline *pipeline, CoglPipelineVertendPrivate *priv) { cogl_object_set_user_data (COGL_OBJECT (pipeline), &glsl_priv_key, priv, destroy_glsl_priv); }
static void dirty_glsl_shader_state (CoglPipeline *pipeline) { cogl_object_set_user_data (COGL_OBJECT (pipeline), &glsl_priv_key, NULL, destroy_glsl_priv); }
static void set_shader_state (CoglPipeline *pipeline, CoglPipelineShaderState *shader_state) { cogl_object_set_user_data (COGL_OBJECT (pipeline), &shader_state_key, shader_state, destroy_shader_state); }
CoglPipeline * _cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache, CoglHandle texture) { CoglPangoPipelineCacheEntry *entry; PipelineDestroyNotifyData *destroy_data; static CoglUserDataKey pipeline_destroy_notify_key; /* Look for an existing entry */ entry = g_hash_table_lookup (cache->hash_table, texture); if (entry) return cogl_object_ref (entry->pipeline); /* No existing pipeline was found so let's create another */ entry = g_slice_new (CoglPangoPipelineCacheEntry); if (texture) { CoglPipeline *base; entry->texture = cogl_object_ref (texture); if (cogl_texture_get_format (entry->texture) == COGL_PIXEL_FORMAT_A_8) base = get_base_texture_alpha_pipeline (cache); else base = get_base_texture_rgba_pipeline (cache); entry->pipeline = cogl_pipeline_copy (base); cogl_pipeline_set_layer_texture (entry->pipeline, 0 /* layer */, texture); } else { entry->texture = NULL; entry->pipeline = cogl_pipeline_new (); } /* Add a weak reference to the pipeline so we can remove it from the hash table when it is destroyed */ destroy_data = g_slice_new (PipelineDestroyNotifyData); destroy_data->cache = cache; destroy_data->texture = texture; cogl_object_set_user_data (entry->pipeline, &pipeline_destroy_notify_key, destroy_data, pipeline_destroy_notify_cb); g_hash_table_insert (cache->hash_table, texture ? cogl_object_ref (texture) : NULL, entry); /* This doesn't take a reference on the pipeline so that it will use the newly created reference */ return entry->pipeline; }
static void _rut_camera_flush_transforms (RutCamera *camera) { const CoglMatrix *projection; CoglFramebuffer *fb = camera->fb; CameraFlushState *state; /* While a camera is in a suspended state then we don't expect to * _flush() and use that camera before it is restored. */ g_return_if_fail (camera->suspended == FALSE); state = cogl_object_get_user_data (COGL_OBJECT (fb), &fb_camera_key); if (!state) { state = g_slice_new (CameraFlushState); cogl_object_set_user_data (COGL_OBJECT (fb), &fb_camera_key, state, free_camera_flush_state); } else if (state->current_camera == camera && camera->transform_age == state->transform_age) goto done; if (camera->in_frame) { g_warning ("Un-balanced rut_camera_flush/_end calls: " "repeat _flush() calls before _end()"); } cogl_framebuffer_set_viewport (fb, camera->viewport[0], camera->viewport[1], camera->viewport[2], camera->viewport[3]); projection = rut_camera_get_projection (camera); cogl_framebuffer_set_projection_matrix (fb, projection); cogl_framebuffer_set_modelview_matrix (fb, &camera->view); state->current_camera = camera; state->transform_age = camera->transform_age; done: camera->in_frame = TRUE; }
CoglBitmap * _cogl_bitmap_from_file (const char *filename, GError **error) { static CoglUserDataKey pixbuf_key; GdkPixbuf *pixbuf; CoglBool has_alpha; GdkColorspace color_space; CoglPixelFormat pixel_format; int width; int height; int rowstride; int bits_per_sample; int n_channels; CoglBitmap *bmp; _COGL_GET_CONTEXT (ctx, NULL); _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, FALSE); /* Load from file using GdkPixbuf */ pixbuf = gdk_pixbuf_new_from_file (filename, error); if (pixbuf == NULL) return FALSE; /* Get pixbuf properties */ has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); color_space = gdk_pixbuf_get_colorspace (pixbuf); width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf); n_channels = gdk_pixbuf_get_n_channels (pixbuf); /* According to current docs this should be true and so * the translation to cogl pixel format below valid */ g_assert (bits_per_sample == 8); if (has_alpha) g_assert (n_channels == 4); else g_assert (n_channels == 3); /* Translate to cogl pixel format */ switch (color_space) { case GDK_COLORSPACE_RGB: /* The only format supported by GdkPixbuf so far */ pixel_format = has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888; break; default: /* Ouch, spec changed! */ g_object_unref (pixbuf); return FALSE; } /* We just use the data directly from the pixbuf so that we don't have to copy to a seperate buffer. Note that Cogl is expected not to read past the end of bpp*width on the last row even if the rowstride is much larger so we don't need to worry about GdkPixbuf's semantics that it may under-allocate the buffer. */ bmp = cogl_bitmap_new_for_data (ctx, width, height, pixel_format, rowstride, gdk_pixbuf_get_pixels (pixbuf)); cogl_object_set_user_data (COGL_OBJECT (bmp), &pixbuf_key, pixbuf, g_object_unref); return bmp; }
CoglHandle meta_texture_rectangle_new (unsigned int width, unsigned int height, CoglTextureFlags flags, CoglPixelFormat format, GLenum internal_gl_format, GLenum internal_format, unsigned int rowstride, const guint8 *data) { CoglHandle cogl_tex = COGL_INVALID_HANDLE; #ifdef GL_TEXTURE_RECTANGLE_ARB static CoglUserDataKey user_data_key; GLint old_binding; GLuint tex; if (pf_glGenTextures == NULL) { pf_glGetIntegerv = (void *) cogl_get_proc_address ("glGetIntegerv"); pf_glTexImage2D = (void *) cogl_get_proc_address ("glTexImage2D"); pf_glGenTextures = (void *) cogl_get_proc_address ("glGenTextures"); pf_glDeleteTextures = (void *) cogl_get_proc_address ("glDeleteTextures"); pf_glBindTexture = (void *) cogl_get_proc_address ("glBindTexture"); } pf_glGenTextures (1, &tex); pf_glGetIntegerv (GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding); pf_glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex); pf_glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, internal_gl_format, width, height, 0, internal_gl_format, GL_UNSIGNED_BYTE, NULL); pf_glBindTexture (GL_TEXTURE_RECTANGLE_ARB, old_binding); cogl_tex = cogl_texture_new_from_foreign (tex, GL_TEXTURE_RECTANGLE_ARB, width, height, 0, 0, /* no waste */ internal_format); /* Cogl won't destroy the GL texture when a foreign texture is used so we need to destroy it manually. We can set a destroy notification callback to do this transparently */ cogl_object_set_user_data (cogl_tex, &user_data_key, GUINT_TO_POINTER (tex), rectangle_texture_destroy_cb); /* Use cogl_texture_set_region instead of uploading the data directly with GL calls so that we can let Cogl deal with setting the pixel store parameters and handling format conversion */ if (data) cogl_texture_set_region (cogl_tex, 0, 0, /* src x/y */ 0, 0, /* dst x/y */ width, height, /* dst width/height */ width, height, /* src width/height */ format, rowstride, data); #endif /* GL_TEXTURE_RECTANGLE_ARB */ return cogl_tex; }