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; }
void rut_camera_suspend (RutCamera *camera) { CameraFlushState *state; /* There's not point suspending a frame that hasn't been flushed */ g_return_if_fail (camera->in_frame == TRUE); g_return_if_fail (camera->suspended == FALSE); state = cogl_object_get_user_data (COGL_OBJECT (camera->fb), &fb_camera_key); /* We only expect to be saving a camera that has been flushed */ g_return_if_fail (state != NULL); /* While the camera is in a suspended state we aren't expecting the * camera to be touched but we want to double check that at least * the transform hasn't been touched when we come to resume the * camera... */ camera->at_suspend_transform_age = camera->transform_age; /* When we resume the camer we'll need to restore the modelview, * projection and viewport transforms. The easiest way for us to * handle restoring the modelview is to use the framebuffer's * matrix stack... */ cogl_framebuffer_push_matrix (camera->fb); camera->suspended = TRUE; camera->in_frame = FALSE; }
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; }
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; }
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; }
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 dirty_shader_state (CoglPipeline *pipeline) { cogl_object_set_user_data (COGL_OBJECT (pipeline), &shader_state_key, NULL, NULL); }
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); }
static void set_glsl_priv (CoglPipeline *pipeline, CoglPipelineVertendPrivate *priv) { cogl_object_set_user_data (COGL_OBJECT (pipeline), &glsl_priv_key, priv, destroy_glsl_priv); }
void _cogl_texture_associate_framebuffer (CoglHandle handle, CoglFramebuffer *framebuffer) { CoglTexture *tex = COGL_TEXTURE (handle); static CoglUserDataKey framebuffer_destroy_notify_key; /* Note: we don't take a reference on the framebuffer here because * that would introduce a circular reference. */ tex->framebuffers = g_list_prepend (tex->framebuffers, framebuffer); /* Since we haven't taken a reference on the framebuffer we setup * some private data so we will be notified if it is destroyed... */ _cogl_object_set_user_data (COGL_OBJECT (framebuffer), &framebuffer_destroy_notify_key, tex, _cogl_texture_framebuffer_destroy_cb); }
static void set_shader_state (CoglPipeline *pipeline, CoglPipelineShaderState *shader_state) { if (shader_state) { shader_state->ref_count++; /* If we're not setting the state on the template pipeline then * mark it as a usage of the pipeline cache entry */ if (shader_state->cache_entry && shader_state->cache_entry->pipeline != pipeline) shader_state->cache_entry->usage_count++; } _cogl_object_set_user_data (COGL_OBJECT (pipeline), &shader_state_key, shader_state, destroy_shader_state); }
void rut_camera_resume (RutCamera *camera) { CameraFlushState *state; CoglFramebuffer *fb = camera->fb; g_return_if_fail (camera->in_frame == FALSE); g_return_if_fail (camera->suspended == TRUE); /* While a camera is in a suspended state we don't expect the camera * to be touched so its transforms shouldn't have changed... */ g_return_if_fail (camera->at_suspend_transform_age == camera->transform_age); state = cogl_object_get_user_data (COGL_OBJECT (fb), &fb_camera_key); /* We only expect to be restoring a camera that has been flushed * before */ g_return_if_fail (state != NULL); cogl_framebuffer_pop_matrix (fb); /* If the save turned out to be redundant then we have nothing * else to restore... */ if (state->current_camera == camera) goto done; cogl_framebuffer_set_viewport (fb, camera->viewport[0], camera->viewport[1], camera->viewport[2], camera->viewport[3]); cogl_framebuffer_set_projection_matrix (fb, &camera->projection); state->current_camera = camera; state->transform_age = camera->transform_age; done: camera->in_frame = TRUE; camera->suspended = FALSE; }
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; }
static CoglPipelineShaderState * get_shader_state (CoglPipeline *pipeline) { return cogl_object_get_user_data (COGL_OBJECT (pipeline), &shader_state_key); }
static CoglPipelineVertendPrivate * get_glsl_priv (CoglPipeline *pipeline) { return cogl_object_get_user_data (COGL_OBJECT (pipeline), &glsl_priv_key); }
static CoglBool dump_layer_cb (CoglNode *node, void *user_data) { CoglPipelineLayer *layer = COGL_PIPELINE_LAYER (node); PrintDebugState *state = user_data; int layer_id = *state->node_id_ptr; PrintDebugState state_out; GString *changes_label; CoglBool changes = FALSE; if (state->parent_id >= 0) g_string_append_printf (state->graph, "%*slayer%p -> layer%p;\n", state->indent, "", layer->_parent.parent, layer); g_string_append_printf (state->graph, "%*slayer%p [label=\"layer=0x%p\\n" "ref count=%d\" " "color=\"blue\"];\n", state->indent, "", layer, layer, COGL_OBJECT (layer)->ref_count); changes_label = g_string_new (""); g_string_append_printf (changes_label, "%*slayer%p -> layer_state%d [weight=100];\n" "%*slayer_state%d [shape=box label=\"", state->indent, "", layer, layer_id, state->indent, "", layer_id); if (layer->differences & COGL_PIPELINE_LAYER_STATE_UNIT) { changes = TRUE; g_string_append_printf (changes_label, "\\lunit=%u\\n", layer->unit_index); } if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA) { changes = TRUE; g_string_append_printf (changes_label, "\\ltexture=%p\\n", layer->texture); } if (changes) { g_string_append_printf (changes_label, "\"];\n"); g_string_append (state->graph, changes_label->str); g_string_free (changes_label, TRUE); } state_out.parent_id = layer_id; state_out.node_id_ptr = state->node_id_ptr; (*state_out.node_id_ptr)++; state_out.graph = state->graph; state_out.indent = state->indent + 2; _cogl_pipeline_node_foreach_child (COGL_NODE (layer), dump_layer_cb, &state_out); return TRUE; }
static CoglBool dump_pipeline_cb (CoglNode *node, void *user_data) { CoglPipeline *pipeline = COGL_PIPELINE (node); PrintDebugState *state = user_data; int pipeline_id = *state->node_id_ptr; PrintDebugState state_out; GString *changes_label; CoglBool changes = FALSE; CoglBool layers = FALSE; if (state->parent_id >= 0) g_string_append_printf (state->graph, "%*spipeline%d -> pipeline%d;\n", state->indent, "", state->parent_id, pipeline_id); g_string_append_printf (state->graph, "%*spipeline%d [label=\"pipeline=0x%p\\n" "ref count=%d\\n" "breadcrumb=\\\"%s\\\"\" color=\"red\"];\n", state->indent, "", pipeline_id, pipeline, COGL_OBJECT (pipeline)->ref_count, pipeline->has_static_breadcrumb ? #ifdef COGL_DEBUG_ENABLED pipeline->static_breadcrumb : "NULL" #else "NULL" #endif ); changes_label = g_string_new (""); g_string_append_printf (changes_label, "%*spipeline%d -> pipeline_state%d [weight=100];\n" "%*spipeline_state%d [shape=box label=\"", state->indent, "", pipeline_id, pipeline_id, state->indent, "", pipeline_id); if (pipeline->differences & COGL_PIPELINE_STATE_COLOR) { changes = TRUE; g_string_append_printf (changes_label, "\\lcolor=0x%02X%02X%02X%02X\\n", cogl_color_get_red_byte (&pipeline->color), cogl_color_get_green_byte (&pipeline->color), cogl_color_get_blue_byte (&pipeline->color), cogl_color_get_alpha_byte (&pipeline->color)); } if (pipeline->differences & COGL_PIPELINE_STATE_BLEND) { const char *blend_enable_name; changes = TRUE; switch (pipeline->blend_enable) { case COGL_PIPELINE_BLEND_ENABLE_AUTOMATIC: blend_enable_name = "AUTO"; break; case COGL_PIPELINE_BLEND_ENABLE_ENABLED: blend_enable_name = "ENABLED"; break; case COGL_PIPELINE_BLEND_ENABLE_DISABLED: blend_enable_name = "DISABLED"; break; default: blend_enable_name = "UNKNOWN"; } g_string_append_printf (changes_label, "\\lblend=%s\\n", blend_enable_name); } if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS) { changes = TRUE; layers = TRUE; g_string_append_printf (changes_label, "\\ln_layers=%d\\n", pipeline->n_layers); } if (changes) { g_string_append_printf (changes_label, "\"];\n"); g_string_append (state->graph, changes_label->str); g_string_free (changes_label, TRUE); } if (layers) { g_list_foreach (pipeline->layer_differences, (GFunc)dump_layer_ref_cb, state); } state_out.parent_id = pipeline_id; state_out.node_id_ptr = state->node_id_ptr; (*state_out.node_id_ptr)++; state_out.graph = state->graph; state_out.indent = state->indent + 2; _cogl_pipeline_node_foreach_child (COGL_NODE (pipeline), dump_pipeline_cb, &state_out); return TRUE; }