コード例 #1
0
static gboolean
should_use_rectangle (void)
{
  _COGL_GET_CONTEXT (ctxt, FALSE);

  if (ctxt->winsys.rectangle_state == COGL_WINSYS_RECTANGLE_STATE_UNKNOWN)
    {
      if (cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE))
        {
          const char *rect_env;

          /* Use the rectangle only if it is available and either:

             the COGL_PIXMAP_TEXTURE_RECTANGLE environment variable is
             set to 'force'

             *or*

             the env var is set to 'allow' or not set and NPOTs textures
             are not available */

          ctxt->winsys.rectangle_state =
            cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) ?
            COGL_WINSYS_RECTANGLE_STATE_DISABLE :
            COGL_WINSYS_RECTANGLE_STATE_ENABLE;

          if ((rect_env = g_getenv ("COGL_PIXMAP_TEXTURE_RECTANGLE")) ||
              /* For compatibility, we'll also look at the old Clutter
                 environment variable */
              (rect_env = g_getenv ("CLUTTER_PIXMAP_TEXTURE_RECTANGLE")))
            {
              if (g_ascii_strcasecmp (rect_env, "force") == 0)
                ctxt->winsys.rectangle_state =
                  COGL_WINSYS_RECTANGLE_STATE_ENABLE;
              else if (g_ascii_strcasecmp (rect_env, "disable") == 0)
                ctxt->winsys.rectangle_state =
                  COGL_WINSYS_RECTANGLE_STATE_DISABLE;
              else if (g_ascii_strcasecmp (rect_env, "allow"))
                g_warning ("Unknown value for COGL_PIXMAP_TEXTURE_RECTANGLE, "
                           "should be 'force' or 'disable'");
            }
        }
      else
        ctxt->winsys.rectangle_state = COGL_WINSYS_RECTANGLE_STATE_DISABLE;
    }

  return ctxt->winsys.rectangle_state == COGL_WINSYS_RECTANGLE_STATE_ENABLE;
}
コード例 #2
0
ファイル: cogl-vertex-array.c プロジェクト: nobled/clutter
CoglVertexArray *
cogl_vertex_array_new (gsize bytes, const void *data)
{
    CoglVertexArray *array = g_slice_new (CoglVertexArray);
    gboolean use_malloc;

    if (!cogl_features_available (COGL_FEATURE_VBOS))
        use_malloc = TRUE;
    else
        use_malloc = FALSE;

    /* parent's constructor */
    _cogl_buffer_initialize (COGL_BUFFER (array),
                             bytes,
                             use_malloc,
                             COGL_BUFFER_BIND_TARGET_VERTEX_ARRAY,
                             COGL_BUFFER_USAGE_HINT_VERTEX_ARRAY,
                             COGL_BUFFER_UPDATE_HINT_STATIC);

    _cogl_vertex_array_object_new (array);

    if (data)
        cogl_buffer_set_data (COGL_BUFFER (array),
                              0,
                              data,
                              bytes);
    return array;
}
コード例 #3
0
ファイル: cogl-texture-2d.c プロジェクト: gramozeka/GSB-NEW
static gboolean
_cogl_texture_2d_can_create (unsigned int width,
                             unsigned int height,
                             CoglPixelFormat internal_format)
{
  GLenum gl_intformat;
  GLenum gl_type;

  /* If the driver doesn't support glGenerateMipmap then we need to
     store a copy of the first pixels to cause an update. Instead of
     duplicating the code here we'll just make it fallback to
     CoglTexture2DSliced */
  if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
    return FALSE;

  /* If NPOT textures aren't supported then the size must be a power
     of two */
  if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
      (!_cogl_texture_2d_is_pot (width) ||
       !_cogl_texture_2d_is_pot (height)))
    return FALSE;

  _cogl_pixel_format_to_gl (internal_format,
                            &gl_intformat,
                            NULL,
                            &gl_type);

  /* Check that the driver can create a texture with that size */
  if (!_cogl_texture_driver_size_supported (GL_TEXTURE_2D,
                                            gl_intformat,
                                            gl_type,
                                            width,
                                            height))
    return FALSE;

  return TRUE;
}
コード例 #4
0
void
test_cogl_pipeline_uniforms (TestUtilsGTestFixture *fixture,
                             void *user_data)
{
  TestUtilsSharedState *shared_state = user_data;

  /* If shaders aren't supported then we can't run the test */
  if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL))
    {
      TestState state;

      init_state (&state);

      cogl_ortho (/* left, right */
                  0, cogl_framebuffer_get_width (shared_state->fb),
                  /* bottom, top */
                  cogl_framebuffer_get_height (shared_state->fb), 0,
                  /* z near, far */
                  -1, 100);

      paint (&state);
      validate_result ();

      /* Try the test again after querying the location of a large
         number of uniforms. This should verify that the bitmasks
         still work even if they have to allocate a separate array to
         store the bits */

      init_long_pipeline_state (&state);
      paint (&state);
      paint_long_pipeline (&state);
      validate_result ();
      validate_long_pipeline_result ();

      destroy_state (&state);

      if (g_test_verbose ())
        g_print ("OK\n");
    }
  else if (g_test_verbose ())
    g_print ("Skipping\n");
}
コード例 #5
0
ファイル: cogl-pixel-buffer.c プロジェクト: gramozeka/GSB-NEW
CoglHandle
cogl_pixel_buffer_new_EXP (unsigned int size)
{
  CoglPixelBuffer *pixel_buffer = g_slice_new0 (CoglPixelBuffer);
  CoglBuffer *buffer = COGL_BUFFER (pixel_buffer);

  _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);

  /* parent's constructor */
  _cogl_buffer_initialize (buffer,
                           size,
                           COGL_BUFFER_USAGE_HINT_TEXTURE,
                           COGL_BUFFER_UPDATE_HINT_STATIC);

/* malloc version only for GLES */
#if !defined (COGL_HAS_GLES)
  if (cogl_features_available (COGL_FEATURE_PBOS))
    {
      /* PBOS */
      buffer->vtable = &cogl_pixel_buffer_vtable;

      GE( glGenBuffers (1, &buffer->gl_handle) );
      COGL_BUFFER_SET_FLAG (buffer, BUFFER_OBJECT);
    }
  else
#endif
    {
      /* malloc fallback subclass */
      buffer->vtable = &cogl_malloc_pixel_buffer_vtable;

      /* create the buffer here as there's no point for a lazy allocation in
       * the malloc case */
      buffer->data = g_malloc (size);
    }

  pixel_buffer->flags = COGL_PIXEL_BUFFER_FLAG_NONE;

  /* return COGL_INVALID_HANDLE; */
  return _cogl_pixel_buffer_handle_new (pixel_buffer);
}
コード例 #6
0
ファイル: cogl-texture.c プロジェクト: nobled/clutter
static gboolean
get_texture_bits_via_offscreen (CoglHandle      texture_handle,
                                int             x,
                                int             y,
                                int             width,
                                int             height,
                                guint8         *dst_bits,
                                unsigned int    dst_rowstride,
                                CoglPixelFormat dst_format)
{
  CoglFramebuffer *framebuffer;

  _COGL_GET_CONTEXT (ctx, FALSE);

  if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
    return FALSE;

  framebuffer = _cogl_offscreen_new_to_texture_full
                                      (texture_handle,
                                       COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL,
                                       0);

  if (framebuffer == NULL)
    return FALSE;

  cogl_push_framebuffer (framebuffer);

  _cogl_read_pixels_with_rowstride (x, y, width, height,
                                    COGL_READ_PIXELS_COLOR_BUFFER,
                                    dst_format, dst_bits, dst_rowstride);

  cogl_pop_framebuffer ();

  cogl_object_unref (framebuffer);

  return TRUE;
}
コード例 #7
0
ファイル: cogl-clip-stack.c プロジェクト: gramozeka/GSB-NEW
void
_cogl_flush_clip_state (CoglClipStackState *clip_state)
{
  CoglClipStack *stack;
  int has_clip_planes;
  gboolean using_clip_planes = FALSE;
  gboolean using_stencil_buffer = FALSE;
  GList *node;
  int scissor_x0 = 0;
  int scissor_y0 = 0;
  int scissor_x1 = G_MAXINT;
  int scissor_y1 = G_MAXINT;
  CoglMatrixStack *modelview_stack =
    _cogl_framebuffer_get_modelview_stack (_cogl_get_framebuffer ());

  if (!clip_state->stack_dirty)
    return;

  /* The current primitive journal does not support tracking changes to the
   * clip stack...  */
  _cogl_journal_flush ();

  /* XXX: the handling of clipping is quite complex. It may involve use of
   * the Cogl Journal or other Cogl APIs which may end up recursively
   * wanting to ensure the clip state is flushed. We need to ensure we
   * don't recurse infinitely...
   */
  clip_state->stack_dirty = FALSE;

  has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES);

  stack = clip_state->stacks->data;

  clip_state->stencil_used = FALSE;

  disable_clip_planes ();
  disable_stencil_buffer ();
  GE (glDisable (GL_SCISSOR_TEST));

  /* If the stack is empty then there's nothing else to do */
  if (stack->stack_top == NULL)
    return;

  /* Find the bottom of the stack */
  for (node = stack->stack_top; node->next; node = node->next);

  /* Re-add every entry from the bottom of the stack up */
  for (; node; node = node->prev)
    {
      gpointer entry = node->data;
      CoglClipStackEntryType type = *(CoglClipStackEntryType *) entry;

      if (type == COGL_CLIP_STACK_PATH)
        {
          CoglClipStackEntryPath *path = (CoglClipStackEntryPath *) entry;

          _cogl_matrix_stack_push (modelview_stack);
          _cogl_matrix_stack_set (modelview_stack, &path->matrix);

          _cogl_add_path_to_stencil_buffer (path->path_nodes_min,
                                            path->path_nodes_max,
                                            path->path_size,
                                            path->path,
                                            using_stencil_buffer,
                                            TRUE);

          _cogl_matrix_stack_pop (modelview_stack);

          using_stencil_buffer = TRUE;

          /* We can't use clip planes any more */
          has_clip_planes = FALSE;
        }
      else if (type == COGL_CLIP_STACK_RECT)
        {
          CoglClipStackEntryRect *rect = (CoglClipStackEntryRect *) entry;

          _cogl_matrix_stack_push (modelview_stack);
          _cogl_matrix_stack_set (modelview_stack, &rect->matrix);

          /* If this is the first entry and we support clip planes then use
             that instead */
          if (has_clip_planes)
            {
              set_clip_planes (rect->x0,
                               rect->y0,
                               rect->x1,
                               rect->y1);
              using_clip_planes = TRUE;
              /* We can't use clip planes a second time */
              has_clip_planes = FALSE;
            }
          else
            {
              add_stencil_clip_rectangle (rect->x0,
                                          rect->y0,
                                          rect->x1,
                                          rect->y1,
                                          !using_stencil_buffer);
              using_stencil_buffer = TRUE;
            }

          _cogl_matrix_stack_pop (modelview_stack);
        }
      else
        {
          /* Get the intersection of all window space rectangles in the clip
           * stack */
          CoglClipStackEntryWindowRect *window_rect = entry;
          scissor_x0 = MAX (scissor_x0, window_rect->x0);
          scissor_y0 = MAX (scissor_y0, window_rect->y0);
          scissor_x1 = MIN (scissor_x1, window_rect->x1);
          scissor_y1 = MIN (scissor_y1, window_rect->y1);
        }
    }

  /* Enabling clip planes is delayed to now so that they won't affect
     setting up the stencil buffer */
  if (using_clip_planes)
    enable_clip_planes ();

  if (scissor_x0 >= scissor_x1 || scissor_y0 >= scissor_y1)
    scissor_x0 = scissor_y0 = scissor_x1 = scissor_y1 = 0;

  if (!(scissor_x0 == 0 && scissor_y0 == 0 &&
        scissor_x1 == G_MAXINT && scissor_y1 == G_MAXINT))
    {
      GE (glEnable (GL_SCISSOR_TEST));
      GE (glScissor (scissor_x0, scissor_y0,
                     scissor_x1 - scissor_x0,
                     scissor_y1 - scissor_y0));
    }

  clip_state->stencil_used = using_stencil_buffer;
}
コード例 #8
0
static gboolean
_cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
                                   int n_layers,
                                   unsigned long pipelines_difference)
{
  CoglPipelineShaderState *shader_state;
  CoglPipeline *template_pipeline = NULL;
  CoglProgram *user_program;

  _COGL_GET_CONTEXT (ctx, FALSE);

  if (!cogl_features_available (COGL_FEATURE_SHADERS_GLSL))
    return FALSE;

  user_program = cogl_pipeline_get_user_program (pipeline);

  /* If the user program has a vertex shader that isn't GLSL then the
     appropriate vertend for that language should handle it */
  if (user_program &&
      _cogl_program_has_vertex_shader (user_program) &&
      _cogl_program_get_language (user_program) != COGL_SHADER_LANGUAGE_GLSL)
    return FALSE;

  /* Now lookup our glsl backend private state (allocating if
   * necessary) */
  shader_state = get_shader_state (pipeline);

  if (shader_state == NULL)
    {
      CoglPipeline *authority;

      /* Get the authority for anything affecting vertex shader
         state */
      authority = _cogl_pipeline_find_equivalent_parent
        (pipeline,
         COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN &
         ~COGL_PIPELINE_STATE_LAYERS,
         COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN);

      shader_state = get_shader_state (authority);

      if (shader_state == NULL)
        {
          /* Check if there is already a similar cached pipeline whose
             shader state we can share */
          if (G_LIKELY (!(COGL_DEBUG_ENABLED
                          (COGL_DEBUG_DISABLE_PROGRAM_CACHES))))
            {
              template_pipeline =
                _cogl_pipeline_cache_get_vertex_template (ctx->pipeline_cache,
                                                          authority);

              shader_state = get_shader_state (template_pipeline);
            }

          if (shader_state)
            shader_state->ref_count++;
          else
            shader_state = shader_state_new ();

          set_shader_state (authority, shader_state);

          if (template_pipeline)
            {
              shader_state->ref_count++;
              set_shader_state (template_pipeline, shader_state);
            }
        }

      if (authority != pipeline)
        {
          shader_state->ref_count++;
          set_shader_state (pipeline, shader_state);
        }
    }

  if (shader_state->gl_shader)
    {
      /* If we already have a valid GLSL shader then we don't need to
         generate a new one. However if there's a user program and it
         has changed since the last link then we do need a new shader */
      if (user_program == NULL ||
          shader_state->user_program_age == user_program->age)
        return TRUE;

      /* We need to recreate the shader so destroy the existing one */
      GE( ctx, glDeleteShader (shader_state->gl_shader) );
      shader_state->gl_shader = 0;
    }

  /* If we make it here then we have a shader_state struct without a gl_shader
     either because this is the first time we've encountered it or
     because the user program has changed */

  if (user_program)
    shader_state->user_program_age = user_program->age;

  /* If the user program contains a vertex shader then we don't need
     to generate one */
  if (user_program &&
      _cogl_program_has_vertex_shader (user_program))
    return TRUE;

  /* We reuse two grow-only GStrings for code-gen. One string
     contains the uniform and attribute declarations while the
     other contains the main function. We need two strings
     because we need to dynamically declare attributes as the
     add_layer callback is invoked */
  g_string_set_size (ctx->codegen_header_buffer, 0);
  g_string_set_size (ctx->codegen_source_buffer, 0);
  shader_state->header = ctx->codegen_header_buffer;
  shader_state->source = ctx->codegen_source_buffer;

  g_string_append (shader_state->source,
                   "void\n"
                   "main ()\n"
                   "{\n");

  if (ctx->driver == COGL_DRIVER_GLES2)
    /* There is no builtin uniform for the pointsize on GLES2 so we need
       to copy it from the custom uniform in the vertex shader */
    g_string_append (shader_state->source,
                     "  cogl_point_size_out = cogl_point_size_in;\n");
  /* On regular OpenGL we'll just flush the point size builtin */
  else if (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE)
    {
      CoglPipeline *authority =
        _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE);

      if (ctx->point_size_cache != authority->big_state->point_size)
        {
          GE( ctx, glPointSize (authority->big_state->point_size) );
          ctx->point_size_cache = authority->big_state->point_size;
        }
    }

  return TRUE;
}
コード例 #9
0
static GSList *
clutter_gst_build_renderers_list (ClutterGstSymbols *syms)
{
  GSList             *list = NULL;
  const gchar        *gl_extensions;
  GLint               nb_texture_units = 0;
  gint                features = 0, i;
  /* The order of the list of renderers is important. They will be prepended
   * to a GSList and we'll iterate over that list to choose the first matching
   * renderer. Thus if you want to use the fp renderer over the glsl one, the
   * fp renderer has to be put after the glsl one in this array */
  ClutterGstRenderer *renderers[] =
    {
      &rgb24_renderer,
      &rgb32_renderer,
      &yv12_glsl_renderer,
      &i420_glsl_renderer,
#ifdef CLUTTER_COGL_HAS_GL
      &yv12_fp_renderer,
      &i420_fp_renderer,
#endif
      &ayuv_glsl_renderer,
      NULL
    };

  /* get the features */
  gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);

  glGetIntegerv (CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &nb_texture_units);

  if (nb_texture_units >= 3)
    features |= CLUTTER_GST_MULTI_TEXTURE;

#ifdef CLUTTER_COGL_HAS_GL
  if (cogl_check_extension ("GL_ARB_fragment_program", gl_extensions))
    {
      /* the shaders we'll feed to the GPU are simple enough, we don't need
       * to check GL limits for GL_FRAGMENT_PROGRAM_ARB */

      syms->glGenProgramsARB = (GLGENPROGRAMSPROC)
        cogl_get_proc_address ("glGenProgramsARB");
      syms->glBindProgramARB = (GLBINDPROGRAMPROC)
        cogl_get_proc_address ("glBindProgramARB");
      syms->glProgramStringARB = (GLPROGRAMSTRINGPROC)
        cogl_get_proc_address ("glProgramStringARB");

      if (syms->glGenProgramsARB &&
          syms->glBindProgramARB &&
          syms->glProgramStringARB)
        {
          features |= CLUTTER_GST_FP;
        }
    }
#endif

  if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL))
    features |= CLUTTER_GST_GLSL;

  GST_INFO ("GL features: 0x%08x", features);

  for (i = 0; renderers[i]; i++)
    {
      gint needed = renderers[i]->flags;

      if ((needed & features) == needed)
        list = g_slist_prepend (list, renderers[i]);
    }

  return list;
}
コード例 #10
0
static gboolean
get_fbconfig_for_depth (unsigned int depth,
                        GLXFBConfig *fbconfig_ret,
                        gboolean *can_mipmap_ret)
{
  GLXFBConfig *fbconfigs;
  int          n_elements, i;
  Display     *dpy;
  int          db, stencil, alpha, mipmap, rgba, value;
  int          spare_cache_slot = 0;
  gboolean     found = FALSE;

  _COGL_GET_CONTEXT (ctxt, FALSE);

  /* Check if we've already got a cached config for this depth */
  for (i = 0; i < COGL_WINSYS_N_CACHED_CONFIGS; i++)
    if (ctxt->winsys.glx_cached_configs[i].depth == -1)
      spare_cache_slot = i;
    else if (ctxt->winsys.glx_cached_configs[i].depth == depth)
      {
        *fbconfig_ret = ctxt->winsys.glx_cached_configs[i].fb_config;
        *can_mipmap_ret = ctxt->winsys.glx_cached_configs[i].can_mipmap;
        return ctxt->winsys.glx_cached_configs[i].found;
      }

  dpy = _cogl_xlib_get_display ();

  fbconfigs = glXGetFBConfigs (dpy, DefaultScreen (dpy),
                               &n_elements);

  db      = G_MAXSHORT;
  stencil = G_MAXSHORT;
  mipmap  = 0;
  rgba    = 0;

  for (i = 0; i < n_elements; i++)
    {
      XVisualInfo *vi;
      int          visual_depth;

      vi = glXGetVisualFromFBConfig (dpy,
                                     fbconfigs[i]);
      if (vi == NULL)
        continue;

      visual_depth = vi->depth;

      XFree (vi);

      if (visual_depth != depth)
        continue;

      glXGetFBConfigAttrib (dpy,
                            fbconfigs[i],
                            GLX_ALPHA_SIZE,
                            &alpha);
      glXGetFBConfigAttrib (dpy,
                            fbconfigs[i],
                            GLX_BUFFER_SIZE,
                            &value);
      if (value != depth && (value - alpha) != depth)
        continue;

      value = 0;
      if (depth == 32)
        {
          glXGetFBConfigAttrib (dpy,
                                fbconfigs[i],
                                GLX_BIND_TO_TEXTURE_RGBA_EXT,
                                &value);
          if (value)
            rgba = 1;
        }

      if (!value)
        {
          if (rgba)
            continue;

          glXGetFBConfigAttrib (dpy,
                                fbconfigs[i],
                                GLX_BIND_TO_TEXTURE_RGB_EXT,
                                &value);
          if (!value)
            continue;
        }

      glXGetFBConfigAttrib (dpy,
                            fbconfigs[i],
                            GLX_DOUBLEBUFFER,
                            &value);
      if (value > db)
        continue;

      db = value;

      glXGetFBConfigAttrib (dpy,
                            fbconfigs[i],
                            GLX_STENCIL_SIZE,
                            &value);
      if (value > stencil)
        continue;

      stencil = value;

      /* glGenerateMipmap is defined in the offscreen extension */
      if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
        {
          glXGetFBConfigAttrib (dpy,
                                fbconfigs[i],
                                GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
                                &value);

          if (value < mipmap)
            continue;

          mipmap =  value;
        }

      *fbconfig_ret = fbconfigs[i];
      *can_mipmap_ret = mipmap;
      found = TRUE;
    }

  if (n_elements)
    XFree (fbconfigs);

  ctxt->winsys.glx_cached_configs[spare_cache_slot].depth = depth;
  ctxt->winsys.glx_cached_configs[spare_cache_slot].found = found;
  ctxt->winsys.glx_cached_configs[spare_cache_slot].fb_config = *fbconfig_ret;
  ctxt->winsys.glx_cached_configs[spare_cache_slot].can_mipmap = mipmap;

  return found;
}