void cogl_program_uniform_int (int uniform_no, int size, int count, const int *value) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); switch (size) { case 1: glUniform1iv (uniform_no, count, value); break; case 2: glUniform2iv (uniform_no, count, value); break; case 3: glUniform3iv (uniform_no, count, value); break; case 4: glUniform4iv (uniform_no, count, value); break; default: g_warning ("%s called with invalid size parameter", G_STRFUNC); } }
static void _cogl_path_fill_nodes_with_clipped_rectangle (CoglPath *path) { CoglFramebuffer *fb; _COGL_GET_CONTEXT (ctx, NO_RETVAL); if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_STENCIL_BUFFER)) { static gboolean seen_warning = FALSE; if (!seen_warning) { g_warning ("Paths can not be filled using materials with " "sliced textures unless there is a stencil " "buffer"); seen_warning = TRUE; } } fb = cogl_get_draw_framebuffer (); cogl_framebuffer_push_path_clip (fb, path); cogl_rectangle (path->data->path_nodes_min.x, path->data->path_nodes_min.y, path->data->path_nodes_max.x, path->data->path_nodes_max.y); cogl_framebuffer_pop_clip (fb); }
void _cogl_matrix_stack_prepare_for_flush (CoglMatrixStack *stack, CoglMatrixMode mode, CoglMatrixStackFlushFunc callback, void *user_data) { CoglMatrixState *state; _COGL_GET_CONTEXT (ctx, NO_RETVAL); state = _cogl_matrix_stack_top (stack); /* Because Cogl defines texture coordinates to have a top left origin and * because offscreen framebuffers may be used for rendering to textures we * always render upside down to offscreen buffers. */ if (mode == COGL_MATRIX_PROJECTION && cogl_is_offscreen (_cogl_get_draw_buffer ())) { CoglMatrix flipped_projection; CoglMatrix *projection = state->is_identity ? &ctx->identity_matrix : &state->matrix; cogl_matrix_multiply (&flipped_projection, &ctx->y_flip_matrix, projection); callback (FALSE, &flipped_projection, user_data); } else callback (state->is_identity, state->is_identity ? &ctx->identity_matrix : &state->matrix, user_data); }
CoglPath * cogl_get_path (void) { _COGL_GET_CONTEXT (ctx, NULL); return ctx->current_path; }
CoglPathFillRule cogl_path_get_fill_rule (void) { _COGL_GET_CONTEXT (ctx, COGL_PATH_FILL_RULE_EVEN_ODD); return cogl2_path_get_fill_rule (ctx->current_path); }
void cogl_read_pixels (int x, int y, int width, int height, CoglReadPixelsFlags source, CoglPixelFormat format, uint8_t *pixels) { int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); CoglBitmap *bitmap; _COGL_GET_CONTEXT (ctx, NO_RETVAL); bitmap = cogl_bitmap_new_for_data (ctx, width, height, format, bpp * width, /* rowstride */ pixels); cogl_framebuffer_read_pixels_into_bitmap (_cogl_get_read_framebuffer (), x, y, source, bitmap); cogl_object_unref (bitmap); }
void cogl_set_source (void *material_or_pipeline) { CoglSourceState *top; CoglPipeline *pipeline = COGL_PIPELINE (material_or_pipeline); _COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); _COGL_RETURN_IF_FAIL (ctx->source_stack); top = ctx->source_stack->data; if (top->pipeline == pipeline && top->enable_legacy) return; if (top->push_count == 1) { /* NB: top->pipeline may be only thing keeping pipeline * alive currently so ref pipeline first... */ cogl_object_ref (pipeline); cogl_object_unref (top->pipeline); top->pipeline = pipeline; top->enable_legacy = TRUE; } else { top->push_count--; cogl_push_source (pipeline); } }
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 delete_shader (CoglShader *shader) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); #ifdef HAVE_COGL_GL if (shader->language == COGL_SHADER_LANGUAGE_ARBFP) { if (shader->gl_handle) GE (ctx, glDeletePrograms (1, &shader->gl_handle)); } else #endif { if (shader->gl_handle) GE (ctx, glDeleteShader (shader->gl_handle)); } shader->gl_handle = 0; if (shader->compilation_pipeline) { cogl_object_unref (shader->compilation_pipeline); shader->compilation_pipeline = NULL; } }
static CoglBool _cogl_pipeline_progend_fixed_arbfp_start (CoglPipeline *pipeline) { _COGL_GET_CONTEXT (ctx, FALSE); if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED))) return FALSE; if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED)) return FALSE; /* Vertex snippets are only supported in the GLSL fragend */ if (_cogl_pipeline_has_vertex_snippets (pipeline)) return FALSE; /* Validate that we can handle the fragment state using ARBfp */ if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_ARBFP)) return FALSE; /* Fragment snippets are only supported in the GLSL fragend */ if (_cogl_pipeline_has_fragment_snippets (pipeline)) return FALSE; /* The ARBfp progend can't handle the per-vertex point size * attribute */ if (cogl_pipeline_get_per_vertex_point_size (pipeline)) return FALSE; return TRUE; }
CoglTexture * _cogl_atlas_copy_rectangle (CoglAtlas *atlas, int x, int y, int width, int height, CoglPixelFormat internal_format) { CoglTexture *tex; CoglBlitData blit_data; CoglError *ignore_error = NULL; _COGL_GET_CONTEXT (ctx, NULL); /* Create a new texture at the right size */ tex = create_migration_texture (ctx, width, height, internal_format); if (!cogl_texture_allocate (tex, &ignore_error)) { cogl_error_free (ignore_error); cogl_object_unref (tex); return NULL; } /* Blit the data out of the atlas to the new texture. If FBOs aren't available this will end up having to copy the entire atlas texture */ _cogl_blit_begin (&blit_data, tex, atlas->texture); _cogl_blit (&blit_data, x, y, 0, 0, width, height); _cogl_blit_end (&blit_data); return tex; }
static CoglBool _cogl_pipeline_progend_fixed_start (CoglPipeline *pipeline) { _COGL_GET_CONTEXT (ctx, FALSE); if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED))) return FALSE; if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED)) return FALSE; /* Vertex snippets are only supported in the GLSL fragend */ if (_cogl_pipeline_has_vertex_snippets (pipeline)) return FALSE; /* Fragment snippets are only supported in the GLSL fragend */ if (_cogl_pipeline_has_fragment_snippets (pipeline)) return FALSE; /* If there is a user program then the appropriate backend for that * language should handle it. */ if (cogl_pipeline_get_user_program (pipeline)) return FALSE; /* The fixed progend can't handle the per-vertex point size * attribute */ if (cogl_pipeline_get_per_vertex_point_size (pipeline)) return FALSE; return TRUE; }
/* Note: _cogl_bind_gl_texture_transient conceptually has slightly * different semantics to OpenGL's glBindTexture because Cogl never * cares about tracking multiple textures bound to different targets * on the same texture unit. * * glBindTexture lets you bind multiple textures to a single texture * unit if they are bound to different targets. So it does something * like: * unit->current_texture[target] = texture; * * Cogl only lets you associate one texture with the currently active * texture unit, so the target is basically a redundant parameter * that's implicitly set on that texture. * * Technically this is just a thin wrapper around glBindTexture so * actually it does have the GL semantics but it seems worth * mentioning the conceptual difference in case anyone wonders why we * don't associate the gl_texture with a gl_target in the * CoglTextureUnit. */ void _cogl_bind_gl_texture_transient (GLenum gl_target, GLuint gl_texture, CoglBool is_foreign) { CoglTextureUnit *unit; _COGL_GET_CONTEXT (ctx, NO_RETVAL); /* We choose to always make texture unit 1 active for transient * binds so that in the common case where multitexturing isn't used * we can simply ignore the state of this texture unit. Notably we * didn't use a large texture unit (.e.g. (GL_MAX_TEXTURE_UNITS - 1) * in case the driver doesn't have a sparse data structure for * texture units. */ _cogl_set_active_texture_unit (1); unit = _cogl_get_texture_unit (1); /* NB: If we have previously bound a foreign texture to this texture * unit we don't know if that texture has since been deleted and we * are seeing the texture name recycled */ if (unit->gl_texture == gl_texture && !unit->dirty_gl_texture && !unit->is_foreign) return; GE (ctx, glBindTexture (gl_target, gl_texture)); unit->dirty_gl_texture = TRUE; unit->is_foreign = is_foreign; }
static void disable_stencil_buffer (void) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); GE( ctx, glDisable (GL_STENCIL_TEST) ); }
CoglFeatureFlags cogl_get_features (void) { _COGL_GET_CONTEXT (ctx, 0); return ctx->feature_flags; }
void cogl_shader_source (CoglHandle handle, const char *source) { CoglShader *shader; CoglShaderLanguage language; _COGL_GET_CONTEXT (ctx, NO_RETVAL); if (!cogl_is_shader (handle)) return; shader = handle; #ifdef HAVE_COGL_GL if (strncmp (source, "!!ARBfp1.0", 10) == 0) language = COGL_SHADER_LANGUAGE_ARBFP; else #endif language = COGL_SHADER_LANGUAGE_GLSL; /* Delete the old object if the language is changing... */ if (G_UNLIKELY (language != shader->language) && shader->gl_handle) delete_shader (shader); shader->source = g_strdup (source); shader->language = language; }
CoglBool cogl_features_available (CoglFeatureFlags features) { _COGL_GET_CONTEXT (ctx, 0); return (ctx->feature_flags & features) == features; }
void cogl_shader_compile (CoglHandle handle) { CoglShader *shader; _COGL_GET_CONTEXT (ctx, NO_RETVAL); if (!cogl_is_shader (handle)) return; #ifdef HAVE_COGL_GL shader = handle; if (shader->language == COGL_SHADER_LANGUAGE_ARBFP) _cogl_shader_compile_real (handle, NULL); #endif /* XXX: For GLSL we don't actually compile anything until the shader * gets used so we have an opportunity to add some boilerplate to * the shader. * * At the end of the day this is obviously a badly designed API * given that we are having to lie to the user. It was a mistake to * so thinly wrap the OpenGL shader API and the current plan is to * replace it with a pipeline snippets API. */ }
CoglFuncPtr cogl_get_proc_address (const char* name) { _COGL_GET_CONTEXT (ctx, NULL); return _cogl_renderer_get_proc_address (ctx->display->renderer, name, FALSE); }
CoglHandle cogl_create_shader (CoglShaderType type) { CoglShader *shader; _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); switch (type) { case COGL_SHADER_TYPE_VERTEX: case COGL_SHADER_TYPE_FRAGMENT: break; default: g_warning ("Unexpected shader type (0x%08lX) given to " "cogl_create_shader", (unsigned long) type); return COGL_INVALID_HANDLE; } shader = g_slice_new (CoglShader); shader->language = COGL_SHADER_LANGUAGE_GLSL; shader->gl_handle = 0; shader->compilation_pipeline = NULL; shader->type = type; return _cogl_shader_handle_new (shader); }
void cogl_path_close (void) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); cogl2_path_close (ctx->current_path); }
CoglTexture * cogl_texture_new_from_data (int width, int height, CoglTextureFlags flags, CoglPixelFormat format, CoglPixelFormat internal_format, int rowstride, const uint8_t *data) { CoglError *ignore_error = NULL; CoglTexture *tex; _COGL_GET_CONTEXT (ctx, NULL); tex = _cogl_texture_new_from_data (ctx, width, height, flags, format, internal_format, rowstride, data, &ignore_error); if (!tex) cogl_error_free (ignore_error); return tex; }
void cogl_path_set_fill_rule (CoglPathFillRule fill_rule) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); cogl2_path_set_fill_rule (ctx->current_path, fill_rule); }
CoglTexture * cogl_texture_new_from_file (const char *filename, CoglTextureFlags flags, CoglPixelFormat internal_format, CoglError **error) { CoglBitmap *bmp; CoglTexture *texture = NULL; _COGL_GET_CONTEXT (ctx, NULL); _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, NULL); bmp = cogl_bitmap_new_from_file (filename, error); if (bmp == NULL) return NULL; texture = _cogl_texture_new_from_bitmap (bmp, flags, internal_format, TRUE, /* can convert in-place */ error); cogl_object_unref (bmp); return texture; }
void cogl_path_stroke_preserve (void) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); cogl2_path_stroke (ctx->current_path); }
void _cogl_features_init (void) { CoglFeatureFlags flags = 0; int max_clip_planes = 0; GLint num_stencil_bits = 0; _COGL_GET_CONTEXT (ctx, NO_RETVAL); GE( glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) ); /* We need at least three stencil bits to combine clips */ if (num_stencil_bits > 2) flags |= COGL_FEATURE_STENCIL_BUFFER; GE( glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) ); if (max_clip_planes >= 4) flags |= COGL_FEATURE_FOUR_CLIP_PLANES; #ifdef HAVE_COGL_GLES2 flags |= COGL_FEATURE_SHADERS_GLSL | COGL_FEATURE_OFFSCREEN; #endif flags |= COGL_FEATURE_VBOS; /* Cache features */ ctx->feature_flags = flags; ctx->features_cached = TRUE; }
CoglPipelineCache * _cogl_pipeline_cache_new (void) { CoglPipelineCache *cache = g_new (CoglPipelineCache, 1); unsigned long vertex_state; unsigned long layer_vertex_state; unsigned int fragment_state; unsigned int layer_fragment_state; _COGL_GET_CONTEXT (ctx, 0); vertex_state = _cogl_pipeline_get_state_for_vertex_codegen (ctx); layer_vertex_state = COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN; fragment_state = _cogl_pipeline_get_state_for_fragment_codegen (ctx); layer_fragment_state = _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx); _cogl_pipeline_hash_table_init (&cache->vertex_hash, vertex_state, layer_vertex_state, "vertex shaders"); _cogl_pipeline_hash_table_init (&cache->fragment_hash, fragment_state, layer_fragment_state, "fragment shaders"); _cogl_pipeline_hash_table_init (&cache->combined_hash, vertex_state | fragment_state, layer_vertex_state | layer_fragment_state, "programs"); return cache; }
CoglBool cogl_get_backface_culling_enabled (void) { _COGL_GET_CONTEXT (ctx, FALSE); return ctx->legacy_backface_culling_enabled; }
/* FIXME: we should distinguish renderer and context features */ gboolean _cogl_winsys_has_feature (CoglWinsysFeature feature) { _COGL_GET_CONTEXT (ctx, FALSE); return COGL_FLAGS_GET (ctx->winsys_features, feature); }
void cogl_program_uniform_1i (int uniform_no, int value) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); glUniform1i (uniform_no, value); }