static gboolean
_cogl_pipeline_fragend_fixed_add_layer (CoglPipeline *pipeline,
                                        CoglPipelineLayer *layer,
                                        unsigned long layers_difference)
{
  CoglTextureUnit *unit =
    _cogl_get_texture_unit (_cogl_pipeline_layer_get_unit_index (layer));
  int unit_index = unit->index;
  int n_rgb_func_args;
  int n_alpha_func_args;

  _COGL_GET_CONTEXT (ctx, FALSE);

  /* XXX: Beware that since we are changing the active texture unit we
   * must make sure we don't call into other Cogl components that may
   * temporarily bind texture objects to query/modify parameters since
   * they will end up binding texture unit 1. See
   * _cogl_bind_gl_texture_transient for more details.
   */
  _cogl_set_active_texture_unit (unit_index);

  if (G_UNLIKELY (unit_index >= get_max_texture_units ()))
    {
      _cogl_disable_texture_unit (unit_index);
      /* TODO: although this isn't considered an error that
       * warrants falling back to a different backend we
       * should print a warning here. */
      return TRUE;
    }

  /* Handle enabling or disabling the right texture target */
  if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET)
    {
      CoglPipelineLayer *tex_authority =
        _cogl_pipeline_layer_get_authority (layer,
                                            COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
      CoglPipelineLayer *target_authority =
        _cogl_pipeline_layer_get_authority (layer,
                                            COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET);
      /* XXX: currently layers with no associated texture fallback to
       * using ctx->default_gl_texture_2d_tex so they have a texture
       * target of GL_TEXTURE_2D */
      GLenum gl_target =
        tex_authority->texture ? target_authority->target : GL_TEXTURE_2D;

      _cogl_set_active_texture_unit (unit_index);

      /* The common GL code handles binding the right texture so we
         just need to handle enabling and disabling it */

      if (unit->enabled_gl_target != gl_target)
        {
          /* Disable the previous target if it's still enabled */
          if (unit->enabled_gl_target)
            GE (ctx, glDisable (unit->enabled_gl_target));

          /* Enable the new target */
          if (!G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING)))
            {
              GE (ctx, glEnable (gl_target));
              unit->enabled_gl_target = gl_target;
            }
        }
    }
  else
    {
      /* Even though there may be no difference between the last flushed
       * texture state and the current layers texture state it may be that the
       * texture unit has been disabled for some time so we need to assert that
       * it's enabled now.
       */
      if (!G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING)) &&
          unit->enabled_gl_target == 0)
        {
          _cogl_set_active_texture_unit (unit_index);
          GE (ctx, glEnable (unit->gl_target));
          unit->enabled_gl_target = unit->gl_target;
        }
    }

  if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE)
    {
      CoglPipelineLayer *authority =
        _cogl_pipeline_layer_get_authority (layer,
                                            COGL_PIPELINE_LAYER_STATE_COMBINE);
      CoglPipelineLayerBigState *big_state = authority->big_state;

      GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE));

      /* Set the combiner functions... */
      GE (ctx, glTexEnvi (GL_TEXTURE_ENV,
                          GL_COMBINE_RGB,
                          big_state->texture_combine_rgb_func));
      GE (ctx, glTexEnvi (GL_TEXTURE_ENV,
                          GL_COMBINE_ALPHA,
                          big_state->texture_combine_alpha_func));

      /*
       * Setup the function arguments...
       */

      /* For the RGB components... */
      n_rgb_func_args =
        _cogl_get_n_args_for_combine_func (big_state->texture_combine_rgb_func);

      GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB,
                          big_state->texture_combine_rgb_src[0]));
      GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB,
                          big_state->texture_combine_rgb_op[0]));
      if (n_rgb_func_args > 1)
        {
          GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB,
                              big_state->texture_combine_rgb_src[1]));
          GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB,
                              big_state->texture_combine_rgb_op[1]));
        }
      if (n_rgb_func_args > 2)
        {
          GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_RGB,
                              big_state->texture_combine_rgb_src[2]));
          GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_RGB,
                              big_state->texture_combine_rgb_op[2]));
        }

      /* For the Alpha component */
      n_alpha_func_args =
        _cogl_get_n_args_for_combine_func (big_state->texture_combine_alpha_func);

      GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA,
                          big_state->texture_combine_alpha_src[0]));
      GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA,
                          big_state->texture_combine_alpha_op[0]));
      if (n_alpha_func_args > 1)
        {
          GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA,
                              big_state->texture_combine_alpha_src[1]));
          GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA,
                              big_state->texture_combine_alpha_op[1]));
        }
      if (n_alpha_func_args > 2)
        {
          GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_ALPHA,
                              big_state->texture_combine_alpha_src[2]));
          GE (ctx, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA,
                              big_state->texture_combine_alpha_op[2]));
        }
    }

  if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT)
    {
      CoglPipelineLayer *authority =
        _cogl_pipeline_layer_get_authority
        (layer, COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT);
      CoglPipelineLayerBigState *big_state = authority->big_state;

      GE (ctx, glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
                           big_state->texture_combine_constant));
    }

  return TRUE;
}
Exemple #2
0
static void
setup_legacy_buffered_attribute (CoglContext *ctx,
                                 CoglPipeline *pipeline,
                                 CoglAttribute *attribute,
                                 uint8_t *base)
{
  switch (attribute->name_state->name_id)
    {
    case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
      _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
                         COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY, TRUE);
      GE (ctx, glColorPointer (attribute->d.buffered.n_components,
                               attribute->d.buffered.type,
                               attribute->d.buffered.stride,
                               base + attribute->d.buffered.offset));
      break;
    case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
      _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
                         COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY, TRUE);
      GE (ctx, glNormalPointer (attribute->d.buffered.type,
                                attribute->d.buffered.stride,
                                base + attribute->d.buffered.offset));
      break;
    case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
      {
        int layer_number = attribute->name_state->layer_number;
        const CoglPipelineGetLayerFlags flags =
          COGL_PIPELINE_GET_LAYER_NO_CREATE;
        CoglPipelineLayer *layer =
          _cogl_pipeline_get_layer_with_flags (pipeline, layer_number, flags);

        if (layer)
          {
            int unit = _cogl_pipeline_layer_get_unit_index (layer);

            _cogl_bitmask_set (&ctx->enable_texcoord_attributes_tmp,
                               unit,
                               TRUE);

            GE (ctx, glClientActiveTexture (GL_TEXTURE0 + unit));
            GE (ctx, glTexCoordPointer (attribute->d.buffered.n_components,
                                        attribute->d.buffered.type,
                                        attribute->d.buffered.stride,
                                        base + attribute->d.buffered.offset));
          }
        break;
      }
    case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
      _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
                         COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY, TRUE);
      GE (ctx, glVertexPointer (attribute->d.buffered.n_components,
                                attribute->d.buffered.type,
                                attribute->d.buffered.stride,
                                base + attribute->d.buffered.offset));
      break;
    case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
#ifdef COGL_PIPELINE_PROGEND_GLSL
      if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_PROGRAMMABLE))
        setup_generic_buffered_attribute (ctx, pipeline, attribute, base);
#endif
      break;
    default:
      g_warn_if_reached ();
    }
}
void
_cogl_buffer_gl_destroy (CoglBuffer *buffer)
{
  GE( buffer->context, glDeleteBuffers (1, &buffer->gl_handle) );
}
Exemple #4
0
/* returns name of given GUID */
const char *debugstr_dmguid (const GUID *id) {
	static const guid_info guids[] = {
		/* CLSIDs */
		GE(CLSID_AudioVBScript),
		GE(CLSID_DirectMusic),
		GE(CLSID_DirectMusicAudioPath),
		GE(CLSID_DirectMusicAudioPathConfig),
		GE(CLSID_DirectMusicAuditionTrack),
		GE(CLSID_DirectMusicBand),
		GE(CLSID_DirectMusicBandTrack),
		GE(CLSID_DirectMusicChordMapTrack),
		GE(CLSID_DirectMusicChordMap),
		GE(CLSID_DirectMusicChordTrack),
		GE(CLSID_DirectMusicCollection),
		GE(CLSID_DirectMusicCommandTrack),
		GE(CLSID_DirectMusicComposer),
		GE(CLSID_DirectMusicContainer),
		GE(CLSID_DirectMusicGraph),
		GE(CLSID_DirectMusicLoader),
		GE(CLSID_DirectMusicLyricsTrack),
		GE(CLSID_DirectMusicMarkerTrack),
		GE(CLSID_DirectMusicMelodyFormulationTrack),
		GE(CLSID_DirectMusicMotifTrack),
		GE(CLSID_DirectMusicMuteTrack),
		GE(CLSID_DirectMusicParamControlTrack),
		GE(CLSID_DirectMusicPatternTrack),
		GE(CLSID_DirectMusicPerformance),
		GE(CLSID_DirectMusicScript),
		GE(CLSID_DirectMusicScriptAutoImpSegment),
		GE(CLSID_DirectMusicScriptAutoImpPerformance),
		GE(CLSID_DirectMusicScriptAutoImpSegmentState),
		GE(CLSID_DirectMusicScriptAutoImpAudioPathConfig),
		GE(CLSID_DirectMusicScriptAutoImpAudioPath),
		GE(CLSID_DirectMusicScriptAutoImpSong),
		GE(CLSID_DirectMusicScriptSourceCodeLoader),
		GE(CLSID_DirectMusicScriptTrack),
		GE(CLSID_DirectMusicSection),
		GE(CLSID_DirectMusicSegment),
		GE(CLSID_DirectMusicSegmentState),
		GE(CLSID_DirectMusicSegmentTriggerTrack),
		GE(CLSID_DirectMusicSegTriggerTrack),
		GE(CLSID_DirectMusicSeqTrack),
		GE(CLSID_DirectMusicSignPostTrack),
		GE(CLSID_DirectMusicSong),
		GE(CLSID_DirectMusicStyle),
		GE(CLSID_DirectMusicStyleTrack),
		GE(CLSID_DirectMusicSynth),
		GE(CLSID_DirectMusicSynthSink),
		GE(CLSID_DirectMusicSysExTrack),
		GE(CLSID_DirectMusicTemplate),
		GE(CLSID_DirectMusicTempoTrack),
		GE(CLSID_DirectMusicTimeSigTrack),
		GE(CLSID_DirectMusicWaveTrack),
		GE(CLSID_DirectSoundWave),
		/* IIDs */
		GE(IID_IDirectMusic),
		GE(IID_IDirectMusic2),
		GE(IID_IDirectMusic8),
		GE(IID_IDirectMusicAudioPath),
		GE(IID_IDirectMusicBand),
		GE(IID_IDirectMusicBuffer),
		GE(IID_IDirectMusicChordMap),
		GE(IID_IDirectMusicCollection),
		GE(IID_IDirectMusicComposer),
		GE(IID_IDirectMusicContainer),
		GE(IID_IDirectMusicDownload),
		GE(IID_IDirectMusicDownloadedInstrument),
		GE(IID_IDirectMusicGetLoader),
		GE(IID_IDirectMusicGraph),
		GE(IID_IDirectMusicInstrument),
		GE(IID_IDirectMusicLoader),
		GE(IID_IDirectMusicLoader8),
		GE(IID_IDirectMusicObject),
		GE(IID_IDirectMusicPatternTrack),
		GE(IID_IDirectMusicPerformance),
		GE(IID_IDirectMusicPerformance2),
		GE(IID_IDirectMusicPerformance8),
		GE(IID_IDirectMusicPort),
		GE(IID_IDirectMusicPortDownload),
		GE(IID_IDirectMusicScript),
		GE(IID_IDirectMusicSegment),
		GE(IID_IDirectMusicSegment2),
		GE(IID_IDirectMusicSegment8),
		GE(IID_IDirectMusicSegmentState),
		GE(IID_IDirectMusicSegmentState8),
		GE(IID_IDirectMusicStyle),
		GE(IID_IDirectMusicStyle8),
		GE(IID_IDirectMusicSynth),
		GE(IID_IDirectMusicSynth8),
		GE(IID_IDirectMusicSynthSink),
		GE(IID_IDirectMusicThru),
		GE(IID_IDirectMusicTool),
		GE(IID_IDirectMusicTool8),
		GE(IID_IDirectMusicTrack),
		GE(IID_IDirectMusicTrack8),
		GE(IID_IUnknown),
		GE(IID_IPersistStream),
		GE(IID_IStream),
		GE(IID_IClassFactory),
		/* GUIDs */
		GE(GUID_DirectMusicAllTypes),
		GE(GUID_NOTIFICATION_CHORD),
		GE(GUID_NOTIFICATION_COMMAND),
		GE(GUID_NOTIFICATION_MEASUREANDBEAT),
		GE(GUID_NOTIFICATION_PERFORMANCE),
		GE(GUID_NOTIFICATION_RECOMPOSE),
		GE(GUID_NOTIFICATION_SEGMENT),
		GE(GUID_BandParam),
		GE(GUID_ChordParam),
		GE(GUID_CommandParam),
		GE(GUID_CommandParam2),
		GE(GUID_CommandParamNext),
		GE(GUID_IDirectMusicBand),
		GE(GUID_IDirectMusicChordMap),
		GE(GUID_IDirectMusicStyle),
		GE(GUID_MuteParam),
		GE(GUID_Play_Marker),
		GE(GUID_RhythmParam),
		GE(GUID_TempoParam),
		GE(GUID_TimeSignature),
		GE(GUID_Valid_Start_Time),
		GE(GUID_Clear_All_Bands),
		GE(GUID_ConnectToDLSCollection),
		GE(GUID_Disable_Auto_Download),
		GE(GUID_DisableTempo),
		GE(GUID_DisableTimeSig),
		GE(GUID_Download),
		GE(GUID_DownloadToAudioPath),
		GE(GUID_Enable_Auto_Download),
		GE(GUID_EnableTempo),
		GE(GUID_EnableTimeSig),
		GE(GUID_IgnoreBankSelectForGM),
		GE(GUID_SeedVariations),
		GE(GUID_StandardMIDIFile),
		GE(GUID_Unload),
		GE(GUID_UnloadFromAudioPath),
		GE(GUID_Variations),
		GE(GUID_PerfMasterTempo),
		GE(GUID_PerfMasterVolume),
		GE(GUID_PerfMasterGrooveLevel),
		GE(GUID_PerfAutoDownload),
		GE(GUID_DefaultGMCollection),
		GE(GUID_Synth_Default),
		GE(GUID_Buffer_Reverb),
		GE(GUID_Buffer_EnvReverb),
		GE(GUID_Buffer_Stereo),
		GE(GUID_Buffer_3D_Dry),
		GE(GUID_Buffer_Mono),
		GE(GUID_DMUS_PROP_GM_Hardware),
		GE(GUID_DMUS_PROP_GS_Capable),
		GE(GUID_DMUS_PROP_GS_Hardware),
		GE(GUID_DMUS_PROP_DLS1),
		GE(GUID_DMUS_PROP_DLS2),
		GE(GUID_DMUS_PROP_Effects),
		GE(GUID_DMUS_PROP_INSTRUMENT2),
		GE(GUID_DMUS_PROP_LegacyCaps),
		GE(GUID_DMUS_PROP_MemorySize),
		GE(GUID_DMUS_PROP_SampleMemorySize),
		GE(GUID_DMUS_PROP_SamplePlaybackRate),
		GE(GUID_DMUS_PROP_SetSynthSink),
		GE(GUID_DMUS_PROP_SinkUsesDSound),
		GE(GUID_DMUS_PROP_SynthSink_DSOUND),
		GE(GUID_DMUS_PROP_SynthSink_WAVE),
		GE(GUID_DMUS_PROP_Volume),
		GE(GUID_DMUS_PROP_WavesReverb),
		GE(GUID_DMUS_PROP_WriteLatency),
		GE(GUID_DMUS_PROP_WritePeriod),
		GE(GUID_DMUS_PROP_XG_Capable),
		GE(GUID_DMUS_PROP_XG_Hardware)
	};

	unsigned int i;

        if (!id) return "(null)";

	for (i = 0; i < sizeof(guids)/sizeof(guids[0]); i++) {
		if (IsEqualGUID(id, guids[i].guid))
			return guids[i].name;
	}
	/* if we didn't find it, act like standard debugstr_guid */	
	return debugstr_guid(id);
}	
void
_cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target)
{
  GE( _cogl_wrap_glGenerateMipmap (gl_target) );
}
Exemple #6
0
static void
add_stencil_clip_rectangle (CoglFramebuffer *framebuffer,
                            CoglMatrixEntry *modelview_entry,
                            float x_1,
                            float y_1,
                            float x_2,
                            float y_2,
                            CoglBool first)
{
  CoglMatrixStack *projection_stack =
    _cogl_framebuffer_get_projection_stack (framebuffer);
  CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);

  /* NB: This can be called while flushing the journal so we need
   * to be very conservative with what state we change.
   */

  _cogl_context_set_current_projection_entry (ctx,
                                              projection_stack->last_entry);
  _cogl_context_set_current_modelview_entry (ctx, modelview_entry);

  if (first)
    {
      GE( ctx, glEnable (GL_STENCIL_TEST) );

      /* Initially disallow everything */
      GE( ctx, glClearStencil (0) );
      GE( ctx, glClear (GL_STENCIL_BUFFER_BIT) );

      /* Punch out a hole to allow the rectangle */
      GE( ctx, glStencilFunc (GL_NEVER, 0x1, 0x1) );
      GE( ctx, glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE) );

      _cogl_rectangle_immediate (framebuffer,
                                 ctx->stencil_pipeline,
                                 x_1, y_1, x_2, y_2);
    }
  else
    {
      /* Add one to every pixel of the stencil buffer in the
	 rectangle */
      GE( ctx, glStencilFunc (GL_NEVER, 0x1, 0x3) );
      GE( ctx, glStencilOp (GL_INCR, GL_INCR, GL_INCR) );
      _cogl_rectangle_immediate (framebuffer,
                                 ctx->stencil_pipeline,
                                 x_1, y_1, x_2, y_2);

      /* Subtract one from all pixels in the stencil buffer so that
	 only pixels where both the original stencil buffer and the
	 rectangle are set will be valid */
      GE( ctx, glStencilOp (GL_DECR, GL_DECR, GL_DECR) );

      _cogl_context_set_current_projection_entry (ctx, &ctx->identity_entry);
      _cogl_context_set_current_modelview_entry (ctx, &ctx->identity_entry);

      _cogl_rectangle_immediate (framebuffer,
                                 ctx->stencil_pipeline,
                                 -1.0, -1.0, 1.0, 1.0);
    }

  /* Restore the stencil mode */
  GE( ctx, glStencilFunc (GL_EQUAL, 0x1, 0x1) );
  GE( ctx, glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
}
Exemple #7
0
void
_cogl_clip_stack_gl_flush (CoglClipStack *stack,
                           CoglFramebuffer *framebuffer)
{
  CoglContext *ctx = framebuffer->context;
  int has_clip_planes;
  CoglBool using_clip_planes = FALSE;
  CoglBool using_stencil_buffer = FALSE;
  int scissor_x0;
  int scissor_y0;
  int scissor_x1;
  int scissor_y1;
  CoglClipStack *entry;
  int scissor_y_start;

  /* If we have already flushed this state then we don't need to do
     anything */
  if (ctx->current_clip_stack_valid)
    {
      if (ctx->current_clip_stack == stack &&
          (ctx->needs_viewport_scissor_workaround == FALSE ||
           (framebuffer->viewport_age ==
            framebuffer->viewport_age_for_scissor_workaround &&
            ctx->viewport_scissor_workaround_framebuffer ==
            framebuffer)))
        return;

      _cogl_clip_stack_unref (ctx->current_clip_stack);
    }

  ctx->current_clip_stack_valid = TRUE;
  ctx->current_clip_stack = _cogl_clip_stack_ref (stack);

  has_clip_planes =
    _cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES);

  if (has_clip_planes)
    disable_clip_planes (ctx);
  GE( ctx, glDisable (GL_STENCIL_TEST) );

  /* If the stack is empty then there's nothing else to do
   *
   * See comment below about ctx->needs_viewport_scissor_workaround
   */
  if (stack == NULL && !ctx->needs_viewport_scissor_workaround)
    {
      COGL_NOTE (CLIPPING, "Flushed empty clip stack");

      GE (ctx, glDisable (GL_SCISSOR_TEST));
      return;
    }

  /* Calculate the scissor rect first so that if we eventually have to
     clear the stencil buffer then the clear will be clipped to the
     intersection of all of the bounding boxes. This saves having to
     clear the whole stencil buffer */
  _cogl_clip_stack_get_bounds (stack,
                               &scissor_x0, &scissor_y0,
                               &scissor_x1, &scissor_y1);

  /* XXX: ONGOING BUG: Intel viewport scissor
   *
   * Intel gen6 drivers don't correctly handle offset viewports, since
   * primitives aren't clipped within the bounds of the viewport.  To
   * workaround this we push our own clip for the viewport that will
   * use scissoring to ensure we clip as expected.
   *
   * TODO: file a bug upstream!
   */
  if (ctx->needs_viewport_scissor_workaround)
    {
      _cogl_util_scissor_intersect (framebuffer->viewport_x,
                                    framebuffer->viewport_y,
                                    framebuffer->viewport_x +
                                      framebuffer->viewport_width,
                                    framebuffer->viewport_y +
                                      framebuffer->viewport_height,
                                    &scissor_x0, &scissor_y0,
                                    &scissor_x1, &scissor_y1);
      framebuffer->viewport_age_for_scissor_workaround =
        framebuffer->viewport_age;
      ctx->viewport_scissor_workaround_framebuffer =
        framebuffer;
    }

  /* Enable scissoring as soon as possible */
  if (scissor_x0 >= scissor_x1 || scissor_y0 >= scissor_y1)
    scissor_x0 = scissor_y0 = scissor_x1 = scissor_y1 = scissor_y_start = 0;
  else
    {
      /* We store the entry coordinates in Cogl coordinate space
       * but OpenGL requires the window origin to be the bottom
       * left so we may need to convert the incoming coordinates.
       *
       * NB: Cogl forces all offscreen rendering to be done upside
       * down so in this case no conversion is needed.
       */

      if (cogl_is_offscreen (framebuffer))
        scissor_y_start = scissor_y0;
      else
        {
          int framebuffer_height =
            cogl_framebuffer_get_height (framebuffer);

          scissor_y_start = framebuffer_height - scissor_y1;
        }
    }

  COGL_NOTE (CLIPPING, "Flushing scissor to (%i, %i, %i, %i)",
             scissor_x0, scissor_y0,
             scissor_x1, scissor_y1);

  GE (ctx, glEnable (GL_SCISSOR_TEST));
  GE (ctx, glScissor (scissor_x0, scissor_y_start,
                      scissor_x1 - scissor_x0,
                      scissor_y1 - scissor_y0));

  /* Add all of the entries. This will end up adding them in the
     reverse order that they were specified but as all of the clips
     are intersecting it should work out the same regardless of the
     order */
  for (entry = stack; entry; entry = entry->parent)
    {
      switch (entry->type)
        {
        case COGL_CLIP_STACK_PRIMITIVE:
            {
              CoglClipStackPrimitive *primitive_entry =
                (CoglClipStackPrimitive *) entry;

              COGL_NOTE (CLIPPING, "Adding stencil clip for primitive");

              add_stencil_clip_primitive (framebuffer,
                                          primitive_entry->matrix_entry,
                                          primitive_entry->primitive,
                                          primitive_entry->bounds_x1,
                                          primitive_entry->bounds_y1,
                                          primitive_entry->bounds_x2,
                                          primitive_entry->bounds_y2,
                                          using_stencil_buffer,
                                          TRUE);

              using_stencil_buffer = TRUE;
              break;
            }
        case COGL_CLIP_STACK_RECT:
            {
              CoglClipStackRect *rect = (CoglClipStackRect *) entry;

              /* We don't need to do anything extra if the clip for this
                 rectangle was entirely described by its scissor bounds */
              if (!rect->can_be_scissor)
                {
                  /* If we support clip planes and we haven't already used
                     them then use that instead */
                  if (has_clip_planes)
                    {
                      COGL_NOTE (CLIPPING,
                                 "Adding clip planes clip for rectangle");

                      set_clip_planes (framebuffer,
                                       rect->matrix_entry,
                                       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
                    {
                      COGL_NOTE (CLIPPING, "Adding stencil clip for rectangle");

                      add_stencil_clip_rectangle (framebuffer,
                                                  rect->matrix_entry,
                                                  rect->x0,
                                                  rect->y0,
                                                  rect->x1,
                                                  rect->y1,
                                                  !using_stencil_buffer);
                      using_stencil_buffer = TRUE;
                    }
                }
              break;
            }
        case COGL_CLIP_STACK_WINDOW_RECT:
          break;
          /* We don't need to do anything for window space rectangles because
           * their functionality is entirely implemented by the entry bounding
           * box */
        }
    }

  /* 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 (ctx);
}
Exemple #8
0
bool
cg_device_connect(cg_device_t *dev, cg_error_t **error)
{
    uint8_t white_pixel[] = { 0xff, 0xff, 0xff, 0xff };
    const cg_winsys_vtable_t *winsys;
    int i;
    cg_error_t *internal_error = NULL;

    if (dev->connected)
        return true;

    /* Mark as connected now to avoid recursion issues,
     * but revert in error paths */
    dev->connected = true;

    if (!dev->renderer) {
        cg_renderer_t *renderer = cg_renderer_new();
        if (!cg_renderer_connect(renderer, error)) {
            cg_object_unref(renderer);
            dev->connected = false;
            return false;
        }
        cg_device_set_renderer(dev, renderer);
    }

    if (!dev->display) {
        cg_display_t *display = cg_display_new(dev->renderer, NULL);
        if (!cg_display_setup(display, error)) {
            cg_object_unref(display);
            dev->connected = false;
            return false;
        }
        cg_device_set_display(dev, display);
    }

    /* This is duplicated data, but it's much more convenient to have
       the driver attached to the context and the value is accessed a
       lot throughout CGlib */
    dev->driver = dev->renderer->driver;

    /* Again this is duplicated data, but it convenient to be able
     * access these from the context. */
    dev->driver_vtable = dev->renderer->driver_vtable;
    dev->texture_driver = dev->renderer->texture_driver;

    for (i = 0; i < C_N_ELEMENTS(dev->private_features); i++)
        dev->private_features[i] |= dev->renderer->private_features[i];

    winsys = _cg_device_get_winsys(dev);
    if (!winsys->device_init(dev, error)) {
        dev->connected = false;
        return false;
    }

    dev->attribute_name_states_hash =
        c_hash_table_new_full(c_str_hash, c_str_equal, c_free, c_free);
    dev->attribute_name_index_map = NULL;
    dev->n_attribute_names = 0;

    /* The "cg_color_in" attribute needs a deterministic name_index
     * so we make sure it's the first attribute name we register */
    _cg_attribute_register_attribute_name(dev, "cg_color_in");

    dev->uniform_names =
        c_ptr_array_new_with_free_func((c_destroy_func_t)c_free);
    dev->uniform_name_hash = c_hash_table_new(c_str_hash, c_str_equal);
    dev->n_uniform_names = 0;

    /* Initialise the driver specific state */
    _cg_init_feature_overrides(dev);

    /* XXX: ONGOING BUG: Intel viewport scissor
     *
     * Intel gen6 drivers don't currently correctly handle offset
     * viewports, since primitives aren't clipped within the bounds of
     * the viewport.  To workaround this we push our own clip for the
     * viewport that will use scissoring to ensure we clip as expected.
     *
     * TODO: file a bug upstream!
     */
    if (dev->gpu.driver_package == CG_GPU_INFO_DRIVER_PACKAGE_MESA &&
        dev->gpu.architecture == CG_GPU_INFO_ARCHITECTURE_SANDYBRIDGE &&
        !getenv("CG_DISABLE_INTEL_VIEWPORT_SCISSORT_WORKAROUND"))
        dev->needs_viewport_scissor_workaround = true;
    else
        dev->needs_viewport_scissor_workaround = false;

    dev->sampler_cache = _cg_sampler_cache_new(dev);

    _cg_pipeline_init_default_pipeline();
    _cg_pipeline_init_default_layers();
    _cg_pipeline_init_state_hash_functions();
    _cg_pipeline_init_layer_state_hash_functions();

    dev->current_clip_stack_valid = false;
    dev->current_clip_stack = NULL;

    c_matrix_init_identity(&dev->identity_matrix);
    c_matrix_init_identity(&dev->y_flip_matrix);
    c_matrix_scale(&dev->y_flip_matrix, 1, -1, 1);

    dev->texture_units =
        c_array_new(false, false, sizeof(cg_texture_unit_t));

    if (_cg_has_private_feature(dev, CG_PRIVATE_FEATURE_ANY_GL)) {
        /* See cg-pipeline.c for more details about why we leave texture unit
         * 1
         * active by default... */
        dev->active_texture_unit = 1;
        GE(dev, glActiveTexture(GL_TEXTURE1));
    }

    dev->opaque_color_pipeline = cg_pipeline_new(dev);
    dev->codegen_header_buffer = c_string_new("");
    dev->codegen_source_buffer = c_string_new("");

    dev->default_gl_texture_2d_tex = NULL;
    dev->default_gl_texture_3d_tex = NULL;

    dev->framebuffers = NULL;
    dev->current_draw_buffer = NULL;
    dev->current_read_buffer = NULL;
    dev->current_draw_buffer_state_flushed = 0;
    dev->current_draw_buffer_changes = CG_FRAMEBUFFER_STATE_ALL;

    c_list_init(&dev->onscreen_events_queue);
    c_list_init(&dev->onscreen_dirty_queue);

    c_queue_init(&dev->gles2_context_stack);

    dev->current_pipeline = NULL;
    dev->current_pipeline_changes_since_flush = 0;
    dev->current_pipeline_with_color_attrib = false;

    _cg_bitmask_init(&dev->enabled_custom_attributes);
    _cg_bitmask_init(&dev->enable_custom_attributes_tmp);
    _cg_bitmask_init(&dev->changed_bits_tmp);

    dev->max_texture_units = -1;
    dev->max_activateable_texture_units = -1;

    dev->current_gl_program = 0;

    dev->current_gl_dither_enabled = true;
    dev->current_gl_color_mask = CG_COLOR_MASK_ALL;

    dev->gl_blend_enable_cache = false;

    dev->depth_test_enabled_cache = false;
    dev->depth_test_function_cache = CG_DEPTH_TEST_FUNCTION_LESS;
    dev->depth_writing_enabled_cache = true;
    dev->depth_range_near_cache = 0;
    dev->depth_range_far_cache = 1;

    dev->pipeline_cache = _cg_pipeline_cache_new();

    for (i = 0; i < CG_BUFFER_BIND_TARGET_COUNT; i++)
        dev->current_buffer[i] = NULL;

    dev->stencil_pipeline = cg_pipeline_new(dev);

    dev->rectangle_byte_indices = NULL;
    dev->rectangle_short_indices = NULL;
    dev->rectangle_short_indices_len = 0;

    dev->texture_download_pipeline = NULL;
    dev->blit_texture_pipeline = NULL;

#if defined(CG_HAS_GL_SUPPORT)
    if ((dev->driver == CG_DRIVER_GL3)) {
        GLuint vertex_array;

        /* In a forward compatible context, GL 3 doesn't support rendering
         * using the default vertex array object. CGlib doesn't use vertex
         * array objects yet so for now we just create a dummy array
         * object that we will use as our own default object. Eventually
         * it could be good to attach the vertex array objects to
         * cg_primitive_ts */
        dev->glGenVertexArrays(1, &vertex_array);
        dev->glBindVertexArray(vertex_array);
    }
#endif

    dev->current_modelview_entry = NULL;
    dev->current_projection_entry = NULL;
    _cg_matrix_entry_identity_init(&dev->identity_entry);
    _cg_matrix_entry_cache_init(&dev->builtin_flushed_projection);
    _cg_matrix_entry_cache_init(&dev->builtin_flushed_modelview);

    /* Create default textures used for fall backs */
    dev->default_gl_texture_2d_tex =
        cg_texture_2d_new_from_data(dev,
                                    1,
                                    1,
                                    CG_PIXEL_FORMAT_RGBA_8888_PRE,
                                    0, /* rowstride */
                                    white_pixel,
                                    NULL); /* abort on error */

    /* If 3D or rectangle textures aren't supported then these will
     * return errors that we can simply ignore. */
    internal_error = NULL;
    dev->default_gl_texture_3d_tex =
        cg_texture_3d_new_from_data(dev,
                                    1,
                                    1,
                                    1, /* width, height, depth */
                                    CG_PIXEL_FORMAT_RGBA_8888_PRE,
                                    0, /* rowstride */
                                    0, /* image stride */
                                    white_pixel,
                                    &internal_error);
    if (internal_error)
        cg_error_free(internal_error);

    dev->buffer_map_fallback_array = c_byte_array_new();
    dev->buffer_map_fallback_in_use = false;

    c_list_init(&dev->fences);

    dev->atlas_set = cg_atlas_set_new(dev);
    cg_atlas_set_set_components(dev->atlas_set, CG_TEXTURE_COMPONENTS_RGBA);
    cg_atlas_set_set_premultiplied(dev->atlas_set, false);
    cg_atlas_set_add_atlas_callback(dev->atlas_set,
                                    _cg_atlas_texture_atlas_event_handler,
                                    NULL, /* user data */
                                    NULL); /* destroy */

    return true;
}
static CoglBool
_cogl_pipeline_fragend_arbfp_end (CoglPipeline *pipeline,
                                  unsigned long pipelines_difference)
{
  CoglPipelineShaderState *shader_state = get_shader_state (pipeline);
  GLuint gl_program;
  UpdateConstantsState state;

  _COGL_GET_CONTEXT (ctx, FALSE);

  if (shader_state->source)
    {
      GLenum gl_error;
      COGL_STATIC_COUNTER (fragend_arbfp_compile_counter,
                           "arbfp compile counter",
                           "Increments each time a new ARBfp "
                           "program is compiled",
                           0 /* no application private data */);

      COGL_COUNTER_INC (_cogl_uprof_context, fragend_arbfp_compile_counter);

      g_string_append (shader_state->source,
                       "MOV result.color,output;\n");
      g_string_append (shader_state->source, "END\n");

      if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
        g_message ("pipeline program:\n%s", shader_state->source->str);

      GE (ctx, glGenPrograms (1, &shader_state->gl_program));

      GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB,
                              shader_state->gl_program));

      while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
        ;
      ctx->glProgramString (GL_FRAGMENT_PROGRAM_ARB,
                            GL_PROGRAM_FORMAT_ASCII_ARB,
                            shader_state->source->len,
                            shader_state->source->str);
      if (ctx->glGetError () != GL_NO_ERROR)
        {
          g_warning ("\n%s\n%s",
                     shader_state->source->str,
                     ctx->glGetString (GL_PROGRAM_ERROR_STRING_ARB));
        }

      shader_state->source = NULL;
    }

  gl_program = shader_state->gl_program;

  GE (ctx, glBindProgram (GL_FRAGMENT_PROGRAM_ARB, gl_program));
  _cogl_use_fragment_program (0, COGL_PIPELINE_PROGRAM_TYPE_ARBFP);

  state.unit = 0;
  state.shader_state = shader_state;
  /* If this arbfp program was last used with a different pipeline
   * then we need to ensure we update all program.local params */
  state.update_all =
    pipeline != shader_state->last_used_for_pipeline;
  cogl_pipeline_foreach_layer (pipeline,
                               update_constants_cb,
                               &state);

  /* We need to track what pipeline used this arbfp program last since
   * we will need to update program.local params when switching
   * between different pipelines. */
  shader_state->last_used_for_pipeline = pipeline;

  return TRUE;
}
Exemple #10
0
static int
_cogl_texture_2d_get_data (CoglTexture     *tex,
                           CoglPixelFormat  format,
                           unsigned int     rowstride,
                           guint8          *data)
{
  CoglTexture2D   *tex_2d = COGL_TEXTURE_2D (tex);
  int              bpp;
  int              byte_size;
  CoglPixelFormat  closest_format;
  int              closest_bpp;
  GLenum           closest_gl_format;
  GLenum           closest_gl_type;
  CoglBitmap       target_bmp;
  CoglBitmap       new_bmp;
  gboolean         success;
  guint8          *src;
  guint8          *dst;
  int              y;

  /* Default to internal format if none specified */
  if (format == COGL_PIXEL_FORMAT_ANY)
    format = tex_2d->format;

  /* Rowstride from texture width if none specified */
  bpp = _cogl_get_format_bpp (format);
  if (rowstride == 0)
    rowstride = tex_2d->width * bpp;

  /* Return byte size if only that requested */
  byte_size =  tex_2d->height * rowstride;
  if (data == NULL)
    return byte_size;

  closest_format =
    _cogl_texture_driver_find_best_gl_get_data_format (format,
                                                       &closest_gl_format,
                                                       &closest_gl_type);
  closest_bpp = _cogl_get_format_bpp (closest_format);

  target_bmp.width = tex_2d->width;
  target_bmp.height = tex_2d->height;

  /* Is the requested format supported? */
  if (closest_format == format)
    {
      /* Target user data directly */
      target_bmp.format = format;
      target_bmp.rowstride = rowstride;
      target_bmp.data = data;
    }
  else
    {
      /* Target intermediate buffer */
      target_bmp.format = closest_format;
      target_bmp.rowstride = target_bmp.width * closest_bpp;
      target_bmp.data = g_malloc (target_bmp.height * target_bmp.rowstride);
    }

  _cogl_texture_driver_prep_gl_for_pixels_download (target_bmp.rowstride,
                                                    closest_bpp);

  GE( glBindTexture (GL_TEXTURE_2D, tex_2d->gl_texture) );
  if (!_cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_2D,
                                              closest_gl_format,
                                              closest_gl_type,
                                              target_bmp.data))
    {
      /* XXX: In some cases _cogl_texture_2d_download_from_gl may
       * fail to read back the texture data; such as for GLES which doesn't
       * support glGetTexImage, so here we fallback to drawing the texture
       * and reading the pixels from the framebuffer. */
      _cogl_texture_draw_and_read (tex, &target_bmp,
                                   closest_gl_format,
                                   closest_gl_type);
    }

  /* Was intermediate used? */
  if (closest_format != format)
    {
      /* Convert to requested format */
      success = _cogl_bitmap_convert_format_and_premult (&target_bmp,
                                                         &new_bmp,
                                                         format);

      /* Free intermediate data and return if failed */
      g_free (target_bmp.data);
      if (!success)
        return 0;

      /* Copy to user buffer */
      for (y = 0; y < new_bmp.height; ++y)
        {
          src = new_bmp.data + y * new_bmp.rowstride;
          dst = data + y * rowstride;
          memcpy (dst, src, new_bmp.width);
        }

      /* Free converted data */
      g_free (new_bmp.data);
    }

  return byte_size;
}
Exemple #11
0
void
_cg_glsl_shader_set_source_with_boilerplate(cg_device_t *dev,
                                            GLuint shader_gl_handle,
                                            GLenum shader_gl_type,
                                            GLsizei count_in,
                                            const char **strings_in,
                                            const GLint *lengths_in)
{
    const char *vertex_boilerplate;
    const char *fragment_boilerplate;

    const char **strings = c_alloca(sizeof(char *) * (count_in + 6));
    GLint *lengths = c_alloca(sizeof(GLint) * (count_in + 6));
    char *version_string;
    int count = 0;

    vertex_boilerplate = _CG_VERTEX_SHADER_BOILERPLATE;
    fragment_boilerplate = _CG_FRAGMENT_SHADER_BOILERPLATE;

    version_string =
        c_strdup_printf("#version %i\n\n", dev->glsl_version_to_use);

    strings[count] = version_string;
    lengths[count++] = -1;

    if (_cg_has_private_feature(dev, CG_PRIVATE_FEATURE_GL_EMBEDDED) &&
        cg_has_feature(dev, CG_FEATURE_ID_TEXTURE_3D)) {
        static const char texture_3d_extension[] =
            "#extension GL_OES_texture_3D : enable\n";
        strings[count] = texture_3d_extension;
        lengths[count++] = sizeof(texture_3d_extension) - 1;
    }

    if (shader_gl_type == GL_VERTEX_SHADER) {
        if (dev->glsl_version_to_use < 130) {
            strings[count] = "#define in attribute\n"
                             "#define out varying\n";
            lengths[count++] = -1;
        } else {
            /* To support source compatibility with glsl >= 1.3 which has
             * replaced
             * all of the texture sampler functions with one polymorphic
             * texture()
             * function we use the preprocessor to map the old names onto the
             * new
             * name...
             */
            strings[count] = "#define texture2D texture\n"
                             "#define texture3D texture\n"
                             "#define textureRect texture\n";
            lengths[count++] = -1;
        }

        strings[count] = vertex_boilerplate;
        lengths[count++] = strlen(vertex_boilerplate);
    } else if (shader_gl_type == GL_FRAGMENT_SHADER) {
        if (dev->glsl_version_to_use < 130) {
            strings[count] = "#define in varying\n"
                             "\n"
                             "#define cg_color_out gl_FragColor\n"
                             "#define cg_depth_out gl_FragDepth\n";
            lengths[count++] = -1;
        }

        strings[count] = fragment_boilerplate;
        lengths[count++] = strlen(fragment_boilerplate);

        if (dev->glsl_version_to_use >= 130) {
            /* FIXME: Support cg_depth_out. */
            /* To support source compatibility with glsl >= 1.3 which has
             * replaced
             * all of the texture sampler functions with one polymorphic
             * texture()
             * function we use the preprocessor to map the old names onto the
             * new
             * name...
             */
            strings[count] = "#define texture2D texture\n"
                             "#define texture3D texture\n"
                             "#define textureRect texture\n"
                             "\n"
                             "out vec4 cg_color_out;\n";
            //"out vec4 cg_depth_out\n";
            lengths[count++] = -1;
        }
    }

    memcpy(strings + count, strings_in, sizeof(char *) * count_in);
    if (lengths_in)
        memcpy(lengths + count, lengths_in, sizeof(GLint) * count_in);
    else {
        int i;

        for (i = 0; i < count_in; i++)
            lengths[count + i] = -1; /* null terminated */
    }
    count += count_in;

    if (C_UNLIKELY(CG_DEBUG_ENABLED(CG_DEBUG_SHOW_SOURCE))) {
        c_string_t *buf = c_string_new(NULL);
        int i;

        c_string_append_printf(buf,
                               "%s shader:\n",
                               shader_gl_type == GL_VERTEX_SHADER ? "vertex"
                               : "fragment");
        for (i = 0; i < count; i++)
            if (lengths[i] != -1)
                c_string_append_len(buf, strings[i], lengths[i]);
            else
                c_string_append(buf, strings[i]);

        c_message("%s", buf->str);

        c_string_free(buf, true);
    }

    GE(dev,
       glShaderSource(
           shader_gl_handle, count, (const char **)strings, lengths));

    c_free(version_string);
}
Exemple #12
0
static void
_cogl_texture_2d_free (CoglTexture2D *tex_2d)
{
  GE( glDeleteTextures (1, &tex_2d->gl_texture) );
  g_free (tex_2d);
}
static CoglBool
_cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
                                 unsigned long pipelines_difference)
{
  CoglPipelineShaderState *shader_state;

  _COGL_GET_CONTEXT (ctx, FALSE);

  shader_state = get_shader_state (pipeline);

  if (shader_state->source)
    {
      const char *source_strings[2];
      GLint lengths[2];
      GLint compile_status;
      GLuint shader;
      CoglPipelineSnippetData snippet_data;
      CoglPipelineSnippetList *vertex_snippets;

      COGL_STATIC_COUNTER (vertend_glsl_compile_counter,
                           "glsl vertex compile counter",
                           "Increments each time a new GLSL "
                           "vertex shader is compiled",
                           0 /* no application private data */);
      COGL_COUNTER_INC (_cogl_uprof_context, vertend_glsl_compile_counter);

      g_string_append (shader_state->header,
                       "void\n"
                       "cogl_real_vertex_transform ()\n"
                       "{\n"
                       "  cogl_position_out = "
                       "cogl_modelview_projection_matrix * "
                       "cogl_position_in;\n"
                       "}\n");

      g_string_append (shader_state->source,
                       "  cogl_vertex_transform ();\n"
                       "  cogl_color_out = cogl_color_in;\n"
                       "}\n");

      vertex_snippets = get_vertex_snippets (pipeline);

      /* Add hooks for the vertex transform part */
      memset (&snippet_data, 0, sizeof (snippet_data));
      snippet_data.snippets = vertex_snippets;
      snippet_data.hook = COGL_SNIPPET_HOOK_VERTEX_TRANSFORM;
      snippet_data.chain_function = "cogl_real_vertex_transform";
      snippet_data.final_name = "cogl_vertex_transform";
      snippet_data.function_prefix = "cogl_vertex_transform";
      snippet_data.source_buf = shader_state->header;
      _cogl_pipeline_snippet_generate_code (&snippet_data);

      /* Add all of the hooks for vertex processing */
      memset (&snippet_data, 0, sizeof (snippet_data));
      snippet_data.snippets = vertex_snippets;
      snippet_data.hook = COGL_SNIPPET_HOOK_VERTEX;
      snippet_data.chain_function = "cogl_generated_source";
      snippet_data.final_name = "cogl_vertex_hook";
      snippet_data.function_prefix = "cogl_vertex_hook";
      snippet_data.source_buf = shader_state->source;
      _cogl_pipeline_snippet_generate_code (&snippet_data);

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

      /* If there are any snippets then we can't rely on the
         projection matrix to flip the rendering for offscreen buffers
         so we'll need to flip it using an extra statement and a
         uniform */
      if (_cogl_pipeline_has_vertex_snippets (pipeline))
        {
          g_string_append (shader_state->header,
                           "uniform vec4 _cogl_flip_vector;\n");
          g_string_append (shader_state->source,
                           "  cogl_position_out *= _cogl_flip_vector;\n");
        }

      g_string_append (shader_state->source,
                       "}\n");

      GE_RET( shader, ctx, glCreateShader (GL_VERTEX_SHADER) );

      lengths[0] = shader_state->header->len;
      source_strings[0] = shader_state->header->str;
      lengths[1] = shader_state->source->len;
      source_strings[1] = shader_state->source->str;

      _cogl_glsl_shader_set_source_with_boilerplate (ctx,
                                                     NULL,
                                                     shader, GL_VERTEX_SHADER,
                                                     2, /* count */
                                                     source_strings, lengths);

      GE( ctx, glCompileShader (shader) );
      GE( ctx, glGetShaderiv (shader, GL_COMPILE_STATUS, &compile_status) );

      if (!compile_status)
        {
          GLint len = 0;
          char *shader_log;

          GE( ctx, glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &len) );
          shader_log = g_alloca (len);
          GE( ctx, glGetShaderInfoLog (shader, len, &len, shader_log) );
          g_warning ("Shader compilation failed:\n%s", shader_log);
        }

      shader_state->header = NULL;
      shader_state->source = NULL;
      shader_state->gl_shader = shader;
    }

  if ((ctx->private_feature_flags &
       COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM) &&
      (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE))
    {
      CoglPipeline *authority =
        _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE);

      GE( ctx, glPointSize (authority->big_state->point_size) );
    }

  return TRUE;
}
static gboolean
_cogl_pipeline_fragend_fixed_end (CoglPipeline *pipeline,
                                  unsigned long pipelines_difference)
{
  int highest_unit_index = -1;
  int i;

  _COGL_GET_CONTEXT (ctx, FALSE);

  _cogl_pipeline_foreach_layer_internal (pipeline,
                                         get_highest_unit_index_cb,
                                         &highest_unit_index);

  /* Disable additional texture units that may have previously been in use.. */
  for (i = highest_unit_index + 1; i < ctx->texture_units->len; i++)
    _cogl_disable_texture_unit (i);

  if (pipelines_difference & COGL_PIPELINE_STATE_FOG)
    {
      CoglPipeline *authority =
        _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_FOG);
      CoglPipelineFogState *fog_state = &authority->big_state->fog_state;

      if (fog_state->enabled)
        {
          GLfloat fogColor[4];
          GLenum gl_mode = GL_LINEAR;

          fogColor[0] = cogl_color_get_red_float (&fog_state->color);
          fogColor[1] = cogl_color_get_green_float (&fog_state->color);
          fogColor[2] = cogl_color_get_blue_float (&fog_state->color);
          fogColor[3] = cogl_color_get_alpha_float (&fog_state->color);

          GE (ctx, glEnable (GL_FOG));

          GE (ctx, glFogfv (GL_FOG_COLOR, fogColor));

          if (ctx->driver == COGL_DRIVER_GLES1)
            switch (fog_state->mode)
              {
              case COGL_FOG_MODE_LINEAR:
                gl_mode = GL_LINEAR;
                break;
              case COGL_FOG_MODE_EXPONENTIAL:
                gl_mode = GL_EXP;
                break;
              case COGL_FOG_MODE_EXPONENTIAL_SQUARED:
                gl_mode = GL_EXP2;
                break;
              }
          /* TODO: support other modes for GLES2 */

          /* NB: GLES doesn't have glFogi */
          GE (ctx, glFogf (GL_FOG_MODE, gl_mode));
          GE (ctx, glHint (GL_FOG_HINT, GL_NICEST));

          GE (ctx, glFogf (GL_FOG_DENSITY, fog_state->density));
          GE (ctx, glFogf (GL_FOG_START, fog_state->z_near));
          GE (ctx, glFogf (GL_FOG_END, fog_state->z_far));
        }
      else
        GE (ctx, glDisable (GL_FOG));
    }

  return TRUE;
}
Exemple #15
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_driver_update_features (CoglContext *context,
                              CoglError **error)
{
    CoglPrivateFeatureFlags private_flags = 0;
    char **gl_extensions;

    /* We have to special case getting the pointer to the glGetString
       function because we need to use it to determine what functions we
       can expect */
    context->glGetString =
        (void *) _cogl_renderer_get_proc_address (context->display->renderer,
                "glGetString",
                TRUE);

    gl_extensions = _cogl_context_get_gl_extensions (context);

    if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WINSYS)))
    {
        char *all_extensions = g_strjoinv (" ", gl_extensions);

        COGL_NOTE (WINSYS,
                   "Checking features\n"
                   "  GL_VENDOR: %s\n"
                   "  GL_RENDERER: %s\n"
                   "  GL_VERSION: %s\n"
                   "  GL_EXTENSIONS: %s",
                   context->glGetString (GL_VENDOR),
                   context->glGetString (GL_RENDERER),
                   _cogl_context_get_gl_version (context),
                   all_extensions);

        g_free (all_extensions);
    }

    context->glsl_major = 1;
    context->glsl_minor = 0;

    _cogl_gpu_info_init (context, &context->gpu);

    _cogl_feature_check_ext_functions (context,
                                       -1 /* GL major version */,
                                       -1 /* GL minor version */,
                                       gl_extensions);

#ifdef HAVE_COGL_GLES
    if (context->driver == COGL_DRIVER_GLES1)
    {
        int max_clip_planes;
        GE( context, glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) );
        if (max_clip_planes >= 4)
            private_flags |= COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES;
    }
#endif

    if (context->driver == COGL_DRIVER_GLES2)
    {
        /* Note GLES 2 core doesn't support mipmaps for npot textures or
         * repeat modes other than CLAMP_TO_EDGE. */
        COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_GLSL, TRUE);
        COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_OFFSCREEN, TRUE);
        COGL_FLAGS_SET (context->features,
                        COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE);
        COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE);
        COGL_FLAGS_SET (context->features,
                        COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE);

        private_flags |= COGL_PRIVATE_FEATURE_BLEND_CONSTANT;
    }
    else if (context->driver == COGL_DRIVER_GLES1)
        private_flags |= (COGL_PRIVATE_FEATURE_FIXED_FUNCTION |
                          COGL_PRIVATE_FEATURE_ALPHA_TEST |
                          COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM);

    private_flags |= (COGL_PRIVATE_FEATURE_VBOS |
                      COGL_PRIVATE_FEATURE_ANY_GL |
                      COGL_PRIVATE_FEATURE_ALPHA_TEXTURES);

    /* Both GLES 1.1 and GLES 2.0 support point sprites in core */
    COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_POINT_SPRITE, TRUE);

    if (context->glGenRenderbuffers)
        COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_OFFSCREEN, TRUE);

    if (context->glBlitFramebuffer)
        private_flags |= COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT;

    if (_cogl_check_extension ("GL_OES_element_index_uint", gl_extensions))
        COGL_FLAGS_SET (context->features,
                        COGL_FEATURE_ID_UNSIGNED_INT_INDICES, TRUE);

    if (_cogl_check_extension ("GL_OES_depth_texture", gl_extensions))
        COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_TEXTURE, TRUE);

    if (_cogl_check_extension ("GL_OES_texture_npot", gl_extensions))
    {
        COGL_FLAGS_SET (context->features,
                        COGL_FEATURE_ID_TEXTURE_NPOT, TRUE);
        COGL_FLAGS_SET (context->features,
                        COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE);
        COGL_FLAGS_SET (context->features,
                        COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE);
        COGL_FLAGS_SET (context->features,
                        COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, TRUE);
    }
    else if (_cogl_check_extension ("GL_IMG_texture_npot", gl_extensions))
    {
        COGL_FLAGS_SET (context->features,
                        COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE);
        COGL_FLAGS_SET (context->features,
                        COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE);
    }

    if (context->glTexImage3D)
        COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_3D, TRUE);

    if (context->glMapBuffer)
        /* The GL_OES_mapbuffer extension doesn't support mapping for
           read */
        COGL_FLAGS_SET (context->features,
                        COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, TRUE);

    if (context->glEGLImageTargetTexture2D)
        private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE;

    if (_cogl_check_extension ("GL_OES_packed_depth_stencil", gl_extensions))
        private_flags |= COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL;

    if (_cogl_check_extension ("GL_EXT_texture_format_BGRA8888", gl_extensions))
        private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_FORMAT_BGRA8888;

    if (_cogl_check_extension ("GL_EXT_unpack_subimage", gl_extensions))
        private_flags |= COGL_PRIVATE_FEATURE_UNPACK_SUBIMAGE;

    /* Cache features */
    context->private_feature_flags |= private_flags;

    g_strfreev (gl_extensions);

    return TRUE;
}
void
_cogl_boxed_value_set_uniform (CoglContext *ctx,
                               GLint location,
                               const CoglBoxedValue *value)
{
  switch (value->type)
    {
    case COGL_BOXED_NONE:
      break;

    case COGL_BOXED_INT:
      {
        const int *ptr;

        if (value->count == 1)
          ptr = value->v.int_value;
        else
          ptr = value->v.int_array;

        switch (value->size)
          {
          case 1:
            GE( ctx, glUniform1iv (location, value->count, ptr) );
            break;
          case 2:
            GE( ctx, glUniform2iv (location, value->count, ptr) );
            break;
          case 3:
            GE( ctx, glUniform3iv (location, value->count, ptr) );
            break;
          case 4:
            GE( ctx, glUniform4iv (location, value->count, ptr) );
            break;
          }
      }
      break;

    case COGL_BOXED_FLOAT:
      {
        const float *ptr;

        if (value->count == 1)
          ptr = value->v.float_value;
        else
          ptr = value->v.float_array;

        switch (value->size)
          {
          case 1:
            GE( ctx, glUniform1fv (location, value->count, ptr) );
            break;
          case 2:
            GE( ctx, glUniform2fv (location, value->count, ptr) );
            break;
          case 3:
            GE( ctx, glUniform3fv (location, value->count, ptr) );
            break;
          case 4:
            GE( ctx, glUniform4fv (location, value->count, ptr) );
            break;
          }
      }
      break;

    case COGL_BOXED_MATRIX:
      {
        const float *ptr;

        if (value->count == 1)
          ptr = value->v.matrix;
        else
          ptr = value->v.float_array;

        switch (value->size)
          {
          case 2:
            GE( ctx, glUniformMatrix2fv (location, value->count,
                                         FALSE, ptr) );
            break;
          case 3:
            GE( ctx, glUniformMatrix3fv (location, value->count,
                                         FALSE, ptr) );
            break;
          case 4:
            GE( ctx, glUniformMatrix4fv (location, value->count,
                                         FALSE, ptr) );
            break;
          }
      }
      break;
    }
}
Exemple #18
0
/*
 * Convert value x (0..63) to corresponding Base64 character.
 */
static int b64_byte_to_char(unsigned x) {
    return (LT(x, 26) & (x + 'A')) |
           (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
           (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
           (EQ(x, 63) & '/');
}
Exemple #19
0
static void
add_stencil_clip_silhouette (CoglFramebuffer *framebuffer,
                             SilhouettePaintCallback silhouette_callback,
                             CoglMatrixEntry *modelview_entry,
                             float bounds_x1,
                             float bounds_y1,
                             float bounds_x2,
                             float bounds_y2,
                             CoglBool merge,
                             CoglBool need_clear,
                             void *user_data)
{
  CoglMatrixStack *projection_stack =
    _cogl_framebuffer_get_projection_stack (framebuffer);
  CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);

  /* NB: This can be called while flushing the journal so we need
   * to be very conservative with what state we change.
   */

  _cogl_context_set_current_projection_entry (ctx,
                                              projection_stack->last_entry);
  _cogl_context_set_current_modelview_entry (ctx, modelview_entry);

  _cogl_pipeline_flush_gl_state (ctx, ctx->stencil_pipeline,
                                 framebuffer, FALSE, FALSE);

  GE( ctx, glEnable (GL_STENCIL_TEST) );

  GE( ctx, glColorMask (FALSE, FALSE, FALSE, FALSE) );
  GE( ctx, glDepthMask (FALSE) );

  if (merge)
    {
      GE (ctx, glStencilMask (2));
      GE (ctx, glStencilFunc (GL_LEQUAL, 0x2, 0x6));
    }
  else
    {
      /* If we're not using the stencil buffer for clipping then we
         don't need to clear the whole stencil buffer, just the area
         that will be drawn */
      if (need_clear)
        /* If this is being called from the clip stack code then it
           will have set up a scissor for the minimum bounding box of
           all of the clips. That box will likely mean that this
           _cogl_clear won't need to clear the entire
           buffer. _cogl_framebuffer_clear_without_flush4f is used instead
           of cogl_clear because it won't try to flush the journal */
        _cogl_framebuffer_clear_without_flush4f (framebuffer,
                                                 COGL_BUFFER_BIT_STENCIL,
                                                 0, 0, 0, 0);
      else
        {
          /* Just clear the bounding box */
          GE( ctx, glStencilMask (~(GLuint) 0) );
          GE( ctx, glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO) );
          _cogl_rectangle_immediate (framebuffer,
                                     ctx->stencil_pipeline,
                                     bounds_x1, bounds_y1,
                                     bounds_x2, bounds_y2);
        }
      GE (ctx, glStencilMask (1));
      GE (ctx, glStencilFunc (GL_LEQUAL, 0x1, 0x3));
    }

  GE (ctx, glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT));

  silhouette_callback (framebuffer, ctx->stencil_pipeline, user_data);

  if (merge)
    {
      /* Now we have the new stencil buffer in bit 1 and the old
         stencil buffer in bit 0 so we need to intersect them */
      GE (ctx, glStencilMask (3));
      GE (ctx, glStencilFunc (GL_NEVER, 0x2, 0x3));
      GE (ctx, glStencilOp (GL_DECR, GL_DECR, GL_DECR));
      /* Decrement all of the bits twice so that only pixels where the
         value is 3 will remain */

      _cogl_context_set_current_projection_entry (ctx, &ctx->identity_entry);
      _cogl_context_set_current_modelview_entry (ctx, &ctx->identity_entry);

      _cogl_rectangle_immediate (framebuffer, ctx->stencil_pipeline,
                                 -1.0, -1.0, 1.0, 1.0);
      _cogl_rectangle_immediate (framebuffer, ctx->stencil_pipeline,
                                 -1.0, -1.0, 1.0, 1.0);
    }

  GE (ctx, glStencilMask (~(GLuint) 0));
  GE (ctx, glDepthMask (TRUE));
  GE (ctx, glColorMask (TRUE, TRUE, TRUE, TRUE));

  GE (ctx, glStencilFunc (GL_EQUAL, 0x1, 0x1));
  GE (ctx, glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP));
}
Exemple #20
0
void
_cogl_use_fragment_program (GLuint gl_program, CoglPipelineProgramType type)
{
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

  /* If we're changing program type... */
  if (type != ctx->current_fragment_program_type)
    {
      /* ... disable the old type */
      switch (ctx->current_fragment_program_type)
        {
        case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
          /* If the program contains a vertex shader then we shouldn't
             disable it */
          if (ctx->current_vertex_program_type !=
              COGL_PIPELINE_PROGRAM_TYPE_GLSL)
            set_glsl_program (0);
          break;

        case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
#ifdef HAVE_COGL_GL
          GE( ctx, glDisable (GL_FRAGMENT_PROGRAM_ARB) );
#endif
          break;

        case COGL_PIPELINE_PROGRAM_TYPE_FIXED:
          /* don't need to to anything */
          break;
        }

      /* ... and enable the new type */
      switch (type)
        {
        case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
#ifdef HAVE_COGL_GL
          GE( ctx, glEnable (GL_FRAGMENT_PROGRAM_ARB) );
#endif
          break;

        case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
        case COGL_PIPELINE_PROGRAM_TYPE_FIXED:
          /* don't need to to anything */
          break;
        }
    }

  if (type == COGL_PIPELINE_PROGRAM_TYPE_GLSL)
    {
#ifdef COGL_PIPELINE_FRAGEND_GLSL
      set_glsl_program (gl_program);

#else

      g_warning ("Unexpected use of GLSL fragend!");

#endif /* COGL_PIPELINE_FRAGEND_GLSL */
    }
#ifndef COGL_PIPELINE_FRAGEND_ARBFP
  else if (type == COGL_PIPELINE_PROGRAM_TYPE_ARBFP)
    g_warning ("Unexpected use of ARBFP fragend!");
#endif /* COGL_PIPELINE_FRAGEND_ARBFP */

  ctx->current_fragment_program_type = type;
}
Exemple #21
0
static void
set_clip_plane (CoglFramebuffer *framebuffer,
                int plane_num,
		const float *vertex_a,
		const float *vertex_b)
{
  CoglContext *ctx = framebuffer->context;
  float planef[4];
  double planed[4];
  float angle;
  CoglMatrixStack *modelview_stack =
    _cogl_framebuffer_get_modelview_stack (framebuffer);
  CoglMatrixStack *projection_stack =
    _cogl_framebuffer_get_projection_stack (framebuffer);
  CoglMatrix inverse_projection;

  cogl_matrix_stack_get_inverse (projection_stack, &inverse_projection);

  /* Calculate the angle between the axes and the line crossing the
     two points */
  angle = atan2f (vertex_b[1] - vertex_a[1],
                  vertex_b[0] - vertex_a[0]) * (180.0/G_PI);

  cogl_matrix_stack_push (modelview_stack);

  /* Load the inverse of the projection matrix so we can specify the plane
   * in screen coordinates */
  cogl_matrix_stack_set (modelview_stack, &inverse_projection);

  /* Rotate about point a */
  cogl_matrix_stack_translate (modelview_stack,
                               vertex_a[0], vertex_a[1], vertex_a[2]);
  /* Rotate the plane by the calculated angle so that it will connect
     the two points */
  cogl_matrix_stack_rotate (modelview_stack, angle, 0.0f, 0.0f, 1.0f);
  cogl_matrix_stack_translate (modelview_stack,
                               -vertex_a[0], -vertex_a[1], -vertex_a[2]);

  /* Clip planes can only be used when a fixed function backend is in
     use so we know we can directly push this matrix to the builtin
     state */
  _cogl_matrix_entry_flush_to_gl_builtins (ctx,
                                           modelview_stack->last_entry,
                                           COGL_MATRIX_MODELVIEW,
                                           framebuffer,
                                           FALSE /* don't disable flip */);

  planef[0] = 0;
  planef[1] = -1.0;
  planef[2] = 0;
  planef[3] = vertex_a[1];

  switch (ctx->driver)
    {
    default:
      g_assert_not_reached ();
      break;

    case COGL_DRIVER_GLES1:
      GE( ctx, glClipPlanef (plane_num, planef) );
      break;

    case COGL_DRIVER_GL:
    case COGL_DRIVER_GL3:
      planed[0] = planef[0];
      planed[1] = planef[1];
      planed[2] = planef[2];
      planed[3] = planef[3];
      GE( ctx, glClipPlane (plane_num, planed) );
      break;
    }

  cogl_matrix_stack_pop (modelview_stack);
}
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;
}
void
_cogl_glsl_shader_set_source_with_boilerplate (CoglContext *ctx,
                                               const char *version_string,
                                               GLuint shader_gl_handle,
                                               GLenum shader_gl_type,
                                               GLsizei count_in,
                                               const char **strings_in,
                                               const GLint *lengths_in)
{
  const char *vertex_boilerplate;
  const char *fragment_boilerplate;

  const char **strings = g_alloca (sizeof (char *) * (count_in + 4));
  GLint *lengths = g_alloca (sizeof (GLint) * (count_in + 4));
  int count = 0;
  char *tex_coord_declarations = NULL;

  vertex_boilerplate = _COGL_VERTEX_SHADER_BOILERPLATE;
  fragment_boilerplate = _COGL_FRAGMENT_SHADER_BOILERPLATE;

  if (version_string)
    {
      strings[count] = version_string;
      lengths[count++] = -1;
    }

  if (ctx->driver == COGL_DRIVER_GLES2 &&
      cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D))
    {
      static const char texture_3d_extension[] =
        "#extension GL_OES_texture_3D : enable\n";
      strings[count] = texture_3d_extension;
      lengths[count++] = sizeof (texture_3d_extension) - 1;
    }

  if (shader_gl_type == GL_VERTEX_SHADER)
    {
      strings[count] = vertex_boilerplate;
      lengths[count++] = strlen (vertex_boilerplate);
    }
  else if (shader_gl_type == GL_FRAGMENT_SHADER)
    {
      strings[count] = fragment_boilerplate;
      lengths[count++] = strlen (fragment_boilerplate);
    }

  memcpy (strings + count, strings_in, sizeof (char *) * count_in);
  if (lengths_in)
    memcpy (lengths + count, lengths_in, sizeof (GLint) * count_in);
  else
    {
      int i;

      for (i = 0; i < count_in; i++)
        lengths[count + i] = -1; /* null terminated */
    }
  count += count_in;

  if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
    {
      GString *buf = g_string_new (NULL);
      int i;

      g_string_append_printf (buf,
                              "%s shader:\n",
                              shader_gl_type == GL_VERTEX_SHADER ?
                              "vertex" : "fragment");
      for (i = 0; i < count; i++)
        if (lengths[i] != -1)
          g_string_append_len (buf, strings[i], lengths[i]);
        else
          g_string_append (buf, strings[i]);

      g_message ("%s", buf->str);

      g_string_free (buf, TRUE);
    }

  GE( ctx, glShaderSource (shader_gl_handle, count,
                           (const char **) strings, lengths) );

  g_free (tex_coord_declarations);
}
static gboolean
_cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
                                 unsigned long pipelines_difference)
{
  CoglPipelineShaderState *shader_state;

  _COGL_GET_CONTEXT (ctx, FALSE);

  shader_state = get_shader_state (pipeline);

  if (shader_state->source)
    {
      const char *source_strings[2];
      GLint lengths[2];
      GLint compile_status;
      GLuint shader;
      int n_layers;

      COGL_STATIC_COUNTER (vertend_glsl_compile_counter,
                           "glsl vertex compile counter",
                           "Increments each time a new GLSL "
                           "vertex shader is compiled",
                           0 /* no application private data */);
      COGL_COUNTER_INC (_cogl_uprof_context, vertend_glsl_compile_counter);

      g_string_append (shader_state->source,
                       "  cogl_position_out = "
                       "cogl_modelview_projection_matrix * "
                       "cogl_position_in;\n"
                       "  cogl_color_out = cogl_color_in;\n"
                       "}\n");

      GE_RET( shader, ctx, glCreateShader (GL_VERTEX_SHADER) );

      lengths[0] = shader_state->header->len;
      source_strings[0] = shader_state->header->str;
      lengths[1] = shader_state->source->len;
      source_strings[1] = shader_state->source->str;

      n_layers = cogl_pipeline_get_n_layers (pipeline);

      _cogl_shader_set_source_with_boilerplate (shader, GL_VERTEX_SHADER,
                                                n_layers,
                                                2, /* count */
                                                source_strings, lengths);

      GE( ctx, glCompileShader (shader) );
      GE( ctx, glGetShaderiv (shader, GL_COMPILE_STATUS, &compile_status) );

      if (!compile_status)
        {
          GLint len = 0;
          char *shader_log;

          GE( ctx, glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &len) );
          shader_log = g_alloca (len);
          GE( ctx, glGetShaderInfoLog (shader, len, &len, shader_log) );
          g_warning ("Shader compilation failed:\n%s", shader_log);
        }

      shader_state->header = NULL;
      shader_state->source = NULL;
      shader_state->gl_shader = shader;
    }

  return TRUE;
}
Exemple #25
0
uint8_t time_in_range(const time_t begin, const time_t end) {
  if ( EQ(begin,end) ) return 0;
  if ( LT(begin,end) ) return GE(current_time,begin) && LE(current_time,end);
  return GE(current_time,begin)  || LE(current_time,end);
}
Exemple #26
0
void
_cogl_features_init (void)
{
  CoglFeatureFlags  flags = 0;
  const gchar      *gl_extensions;
  GLint             max_clip_planes = 0;
  GLint             num_stencil_bits = 0;

  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

  flags = COGL_FEATURE_TEXTURE_READ_PIXELS;

  gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);

  if (cogl_check_extension ("GL_ARB_texture_non_power_of_two", gl_extensions))
    {
#ifdef HAVE_CLUTTER_OSX
      if (really_enable_npot ())
#endif
        flags |= COGL_FEATURE_TEXTURE_NPOT;
    }

#ifdef GL_YCBCR_MESA
  if (cogl_check_extension ("GL_MESA_ycbcr_texture", gl_extensions))
    {
      flags |= COGL_FEATURE_TEXTURE_YUV;
    }
#endif

  if (cogl_check_extension ("GL_ARB_shader_objects", gl_extensions) &&
      cogl_check_extension ("GL_ARB_vertex_shader", gl_extensions) &&
      cogl_check_extension ("GL_ARB_fragment_shader", gl_extensions))
    {
      ctx->pf_glCreateProgramObjectARB =
	(COGL_PFNGLCREATEPROGRAMOBJECTARBPROC)
	cogl_get_proc_address ("glCreateProgramObjectARB");

      ctx->pf_glCreateShaderObjectARB =
	(COGL_PFNGLCREATESHADEROBJECTARBPROC)
	cogl_get_proc_address ("glCreateShaderObjectARB");

      ctx->pf_glShaderSourceARB =
	(COGL_PFNGLSHADERSOURCEARBPROC)
	cogl_get_proc_address ("glShaderSourceARB");

      ctx->pf_glCompileShaderARB =
	(COGL_PFNGLCOMPILESHADERARBPROC)
	cogl_get_proc_address ("glCompileShaderARB");

      ctx->pf_glAttachObjectARB =
	(COGL_PFNGLATTACHOBJECTARBPROC)
	cogl_get_proc_address ("glAttachObjectARB");

      ctx->pf_glLinkProgramARB =
	(COGL_PFNGLLINKPROGRAMARBPROC)
	cogl_get_proc_address ("glLinkProgramARB");

      ctx->pf_glUseProgramObjectARB =
	(COGL_PFNGLUSEPROGRAMOBJECTARBPROC)
	cogl_get_proc_address ("glUseProgramObjectARB");

      ctx->pf_glGetUniformLocationARB =
	(COGL_PFNGLGETUNIFORMLOCATIONARBPROC)
	cogl_get_proc_address ("glGetUniformLocationARB");

      ctx->pf_glDeleteObjectARB =
	(COGL_PFNGLDELETEOBJECTARBPROC)
	cogl_get_proc_address ("glDeleteObjectARB");

      ctx->pf_glGetInfoLogARB =
	(COGL_PFNGLGETINFOLOGARBPROC)
	cogl_get_proc_address ("glGetInfoLogARB");

      ctx->pf_glGetObjectParameterivARB =
	(COGL_PFNGLGETOBJECTPARAMETERIVARBPROC)
	cogl_get_proc_address ("glGetObjectParameterivARB");

      ctx->pf_glUniform1fARB =
	(COGL_PFNGLUNIFORM1FARBPROC)
	cogl_get_proc_address ("glUniform1fARB");

      ctx->pf_glVertexAttribPointerARB =
	(COGL_PFNGLVERTEXATTRIBPOINTERARBPROC)
	cogl_get_proc_address ("glVertexAttribPointerARB");

      ctx->pf_glEnableVertexAttribArrayARB =
	(COGL_PFNGLENABLEVERTEXATTRIBARRAYARBPROC)
	cogl_get_proc_address ("glEnableVertexAttribArrayARB");

      ctx->pf_glDisableVertexAttribArrayARB =
	(COGL_PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)
	cogl_get_proc_address ("glDisableVertexAttribArrayARB");

      ctx->pf_glUniform2fARB =
	(COGL_PFNGLUNIFORM2FARBPROC)
	cogl_get_proc_address ("glUniform2fARB");

      ctx->pf_glUniform3fARB =
	(COGL_PFNGLUNIFORM3FARBPROC)
	cogl_get_proc_address ("glUniform3fARB");

      ctx->pf_glUniform4fARB =
	(COGL_PFNGLUNIFORM4FARBPROC)
	cogl_get_proc_address ("glUniform4fARB");

      ctx->pf_glUniform1fvARB =
	(COGL_PFNGLUNIFORM1FVARBPROC)
	cogl_get_proc_address ("glUniform1fvARB");

      ctx->pf_glUniform2fvARB =
	(COGL_PFNGLUNIFORM2FVARBPROC)
	cogl_get_proc_address ("glUniform2fvARB");

      ctx->pf_glUniform3fvARB =
	(COGL_PFNGLUNIFORM3FVARBPROC)
	cogl_get_proc_address ("glUniform3fvARB");

      ctx->pf_glUniform4fvARB =
	(COGL_PFNGLUNIFORM4FVARBPROC)
	cogl_get_proc_address ("glUniform4fvARB");

      ctx->pf_glUniform1iARB =
	(COGL_PFNGLUNIFORM1IARBPROC)
	cogl_get_proc_address ("glUniform1iARB");

      ctx->pf_glUniform2iARB =
	(COGL_PFNGLUNIFORM2IARBPROC)
	cogl_get_proc_address ("glUniform2iARB");

      ctx->pf_glUniform3iARB =
	(COGL_PFNGLUNIFORM3IARBPROC)
	cogl_get_proc_address ("glUniform3iARB");

      ctx->pf_glUniform4iARB =
	(COGL_PFNGLUNIFORM4IARBPROC)
	cogl_get_proc_address ("glUniform4iARB");

      ctx->pf_glUniform1ivARB =
	(COGL_PFNGLUNIFORM1IVARBPROC)
	cogl_get_proc_address ("glUniform1ivARB");

      ctx->pf_glUniform2ivARB =
	(COGL_PFNGLUNIFORM2IVARBPROC)
	cogl_get_proc_address ("glUniform2ivARB");

      ctx->pf_glUniform3ivARB =
	(COGL_PFNGLUNIFORM3IVARBPROC)
	cogl_get_proc_address ("glUniform3ivARB");

      ctx->pf_glUniform4ivARB =
	(COGL_PFNGLUNIFORM4IVARBPROC)
	cogl_get_proc_address ("glUniform4ivARB");

      ctx->pf_glUniformMatrix2fvARB =
	(COGL_PFNGLUNIFORMMATRIX2FVARBPROC)
	cogl_get_proc_address ("glUniformMatrix2fvARB");

      ctx->pf_glUniformMatrix3fvARB =
	(COGL_PFNGLUNIFORMMATRIX3FVARBPROC)
	cogl_get_proc_address ("glUniformMatrix3fvARB");

      ctx->pf_glUniformMatrix4fvARB =
	(COGL_PFNGLUNIFORMMATRIX4FVARBPROC)
	cogl_get_proc_address ("glUniformMatrix4fvARB");

      if (ctx->pf_glCreateProgramObjectARB    &&
	  ctx->pf_glCreateShaderObjectARB     &&
	  ctx->pf_glShaderSourceARB           &&
	  ctx->pf_glCompileShaderARB          &&
	  ctx->pf_glAttachObjectARB           &&
	  ctx->pf_glLinkProgramARB            &&
	  ctx->pf_glUseProgramObjectARB       &&
	  ctx->pf_glGetUniformLocationARB     &&
	  ctx->pf_glDeleteObjectARB           &&
	  ctx->pf_glGetInfoLogARB             &&
	  ctx->pf_glGetObjectParameterivARB   &&
	  ctx->pf_glUniform1fARB              &&
	  ctx->pf_glUniform2fARB              &&
	  ctx->pf_glUniform3fARB              &&
	  ctx->pf_glUniform4fARB              &&
	  ctx->pf_glUniform1fvARB             &&
	  ctx->pf_glUniform2fvARB             &&
	  ctx->pf_glUniform3fvARB             &&
	  ctx->pf_glUniform4fvARB             &&
	  ctx->pf_glUniform1iARB              &&
	  ctx->pf_glUniform2iARB              &&
	  ctx->pf_glUniform3iARB              &&
	  ctx->pf_glUniform4iARB              &&
	  ctx->pf_glUniform1ivARB             &&
	  ctx->pf_glUniform2ivARB             &&
	  ctx->pf_glUniform3ivARB             &&
	  ctx->pf_glUniform4ivARB             &&
	  ctx->pf_glUniformMatrix2fvARB       &&
	  ctx->pf_glUniformMatrix3fvARB       &&
	  ctx->pf_glUniformMatrix4fvARB       &&
	  ctx->pf_glVertexAttribPointerARB    &&
	  ctx->pf_glEnableVertexAttribArrayARB &&
	  ctx->pf_glDisableVertexAttribArrayARB)
	flags |= COGL_FEATURE_SHADERS_GLSL;
    }

  if (cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions) ||
      cogl_check_extension ("GL_ARB_framebuffer_object", gl_extensions))
    {
      ctx->pf_glGenRenderbuffersEXT =
	(COGL_PFNGLGENRENDERBUFFERSEXTPROC)
	cogl_get_proc_address ("glGenRenderbuffersEXT");

      ctx->pf_glDeleteRenderbuffersEXT =
	(COGL_PFNGLDELETERENDERBUFFERSEXTPROC)
	cogl_get_proc_address ("glDeleteRenderbuffersEXT");

      ctx->pf_glBindRenderbufferEXT =
	(COGL_PFNGLBINDRENDERBUFFEREXTPROC)
	cogl_get_proc_address ("glBindRenderbufferEXT");

      ctx->pf_glRenderbufferStorageEXT =
	(COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC)
	cogl_get_proc_address ("glRenderbufferStorageEXT");

      ctx->pf_glGenFramebuffersEXT =
	(COGL_PFNGLGENFRAMEBUFFERSEXTPROC)
	cogl_get_proc_address ("glGenFramebuffersEXT");

      ctx->pf_glBindFramebufferEXT =
	(COGL_PFNGLBINDFRAMEBUFFEREXTPROC)
	cogl_get_proc_address ("glBindFramebufferEXT");

      ctx->pf_glFramebufferTexture2DEXT =
	(COGL_PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
	cogl_get_proc_address ("glFramebufferTexture2DEXT");

      ctx->pf_glFramebufferRenderbufferEXT =
	(COGL_PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
	cogl_get_proc_address ("glFramebufferRenderbufferEXT");

      ctx->pf_glCheckFramebufferStatusEXT =
	(COGL_PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
	cogl_get_proc_address ("glCheckFramebufferStatusEXT");

      ctx->pf_glDeleteFramebuffersEXT =
	(COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC)
	cogl_get_proc_address ("glDeleteFramebuffersEXT");

      ctx->pf_glGenerateMipmapEXT =
        (COGL_PFNGLGENERATEMIPMAPEXTPROC)
        cogl_get_proc_address ("glGenerateMipmapEXT");

      if (ctx->pf_glGenRenderbuffersEXT         &&
	  ctx->pf_glBindRenderbufferEXT         &&
	  ctx->pf_glRenderbufferStorageEXT      &&
	  ctx->pf_glGenFramebuffersEXT          &&
	  ctx->pf_glBindFramebufferEXT          &&
	  ctx->pf_glFramebufferTexture2DEXT     &&
	  ctx->pf_glFramebufferRenderbufferEXT  &&
	  ctx->pf_glCheckFramebufferStatusEXT   &&
	  ctx->pf_glDeleteFramebuffersEXT       &&
          ctx->pf_glGenerateMipmapEXT)
	flags |= COGL_FEATURE_OFFSCREEN;
    }

  if (cogl_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
    {
      ctx->pf_glBlitFramebufferEXT =
	(COGL_PFNGLBLITFRAMEBUFFEREXTPROC)
	cogl_get_proc_address ("glBlitFramebufferEXT");

      if (ctx->pf_glBlitFramebufferEXT)
	flags |= COGL_FEATURE_OFFSCREEN_BLIT;
    }

  if (cogl_check_extension ("GL_EXT_framebuffer_multisample", gl_extensions))
    {
      ctx->pf_glRenderbufferStorageMultisampleEXT =
	(COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)
	cogl_get_proc_address ("glRenderbufferStorageMultisampleEXT");

      if (ctx->pf_glRenderbufferStorageMultisampleEXT)
	flags |= COGL_FEATURE_OFFSCREEN_MULTISAMPLE;
    }

  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;

  if (cogl_check_extension ("GL_ARB_vertex_buffer_object", gl_extensions))
    {
      ctx->pf_glGenBuffersARB =
	    (COGL_PFNGLGENBUFFERSARBPROC)
	    cogl_get_proc_address ("glGenBuffersARB");
      ctx->pf_glBindBufferARB =
	    (COGL_PFNGLBINDBUFFERARBPROC)
	    cogl_get_proc_address ("glBindBufferARB");
      ctx->pf_glBufferDataARB =
	    (COGL_PFNGLBUFFERDATAARBPROC)
	    cogl_get_proc_address ("glBufferDataARB");
      ctx->pf_glBufferSubDataARB =
	    (COGL_PFNGLBUFFERSUBDATAARBPROC)
	    cogl_get_proc_address ("glBufferSubDataARB");
      ctx->pf_glDeleteBuffersARB =
	    (COGL_PFNGLDELETEBUFFERSARBPROC)
	    cogl_get_proc_address ("glDeleteBuffersARB");
      ctx->pf_glMapBufferARB =
	    (COGL_PFNGLMAPBUFFERARBPROC)
	    cogl_get_proc_address ("glMapBufferARB");
      ctx->pf_glUnmapBufferARB =
	    (COGL_PFNGLUNMAPBUFFERARBPROC)
	    cogl_get_proc_address ("glUnmapBufferARB");
      if (ctx->pf_glGenBuffersARB
	  && ctx->pf_glBindBufferARB
	  && ctx->pf_glBufferDataARB
	  && ctx->pf_glBufferSubDataARB
	  && ctx->pf_glDeleteBuffersARB
	  && ctx->pf_glMapBufferARB
	  && ctx->pf_glUnmapBufferARB)
      flags |= COGL_FEATURE_VBOS;
    }

  /* These should always be available because they are defined in GL
     1.2, but we can't call it directly because under Windows
     functions > 1.1 aren't exported */
  ctx->pf_glDrawRangeElements =
        (COGL_PFNGLDRAWRANGEELEMENTSPROC)
        cogl_get_proc_address ("glDrawRangeElements");
  ctx->pf_glActiveTexture =
        (COGL_PFNGLACTIVETEXTUREPROC)
        cogl_get_proc_address ("glActiveTexture");
  ctx->pf_glClientActiveTexture =
        (COGL_PFNGLCLIENTACTIVETEXTUREPROC)
        cogl_get_proc_address ("glClientActiveTexture");

  ctx->pf_glBlendEquation =
         (COGL_PFNGLBLENDEQUATIONPROC)
         cogl_get_proc_address ("glBlendEquation");
  ctx->pf_glBlendColor =
         (COGL_PFNGLBLENDCOLORPROC)
         cogl_get_proc_address ("glBlendColor");

  /* Available in 1.4 */
  ctx->pf_glBlendFuncSeparate =
        (COGL_PFNGLBLENDFUNCSEPARATEPROC)
        cogl_get_proc_address ("glBlendFuncSeparate");

  /* Available in 2.0 */
  ctx->pf_glBlendEquationSeparate =
        (COGL_PFNGLBLENDEQUATIONSEPARATEPROC)
        cogl_get_proc_address ("glBlendEquationSeparate");

  /* Cache features */
  ctx->feature_flags = flags;
  ctx->features_cached = TRUE;
}
Exemple #27
0
static void
setup_legacy_const_attribute (CoglContext *ctx,
                              CoglPipeline *pipeline,
                              CoglAttribute *attribute)
{
#ifdef COGL_PIPELINE_PROGEND_GLSL
  if (attribute->name_state->name_id == COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY)
    {
      if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_PROGRAMMABLE))
        setup_generic_const_attribute (ctx, pipeline, attribute);
    }
  else
#endif
    {
      float vector[4] = { 0, 0, 0, 1 };
      float *boxed = attribute->d.constant.boxed.v.float_value;
      int n_components = attribute->d.constant.boxed.size;
      int i;

      for (i = 0; i < n_components; i++)
        vector[i] = boxed[i];

      switch (attribute->name_state->name_id)
        {
        case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
          GE (ctx, glColor4f (vector[0], vector[1], vector[2], vector[3]));
          break;
        case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
          GE (ctx, glNormal3f (vector[0], vector[1], vector[2]));
          break;
        case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
          {
            int layer_number = attribute->name_state->layer_number;
            const CoglPipelineGetLayerFlags flags =
              COGL_PIPELINE_GET_LAYER_NO_CREATE;
            CoglPipelineLayer *layer =
              _cogl_pipeline_get_layer_with_flags (pipeline,
                                                   layer_number,
                                                   flags);

            if (layer)
              {
                int unit = _cogl_pipeline_layer_get_unit_index (layer);

                GE (ctx, glClientActiveTexture (GL_TEXTURE0 + unit));

                GE (ctx, glMultiTexCoord4f (vector[0],
                                            vector[1],
                                            vector[2],
                                            vector[3]));
              }
            break;
          }
        case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
          GE (ctx, glVertex4f (vector[0], vector[1], vector[2], vector[3]));
          break;
        default:
          g_warn_if_reached ();
        }
    }
}
Exemple #28
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;
}
static void
_cogl_texture_driver_gl_generate_mipmaps (CoglContext *ctx,
                                          GLenum gl_target)
{
  GE( ctx, glGenerateMipmap (gl_target) );
}
Exemple #30
0
void
_cogl_read_pixels_with_rowstride (int x,
                                  int y,
                                  int width,
                                  int height,
                                  CoglReadPixelsFlags source,
                                  CoglPixelFormat format,
                                  guint8 *pixels,
                                  int rowstride)
{
    CoglFramebuffer *framebuffer = _cogl_get_read_framebuffer ();
    int              framebuffer_height;
    int              bpp;
    CoglBitmap      *bmp;
    GLenum           gl_intformat;
    GLenum           gl_format;
    GLenum           gl_type;
    CoglPixelFormat  bmp_format;
    gboolean         pack_invert_set;

    _COGL_GET_CONTEXT (ctx, NO_RETVAL);

    _COGL_RETURN_IF_FAIL (source == COGL_READ_PIXELS_COLOR_BUFFER);

    if (width == 1 && height == 1 && !framebuffer->clear_clip_dirty)
    {
        /* If everything drawn so far for this frame is still in the
         * Journal then if all of the rectangles only have a flat
         * opaque color we have a fast-path for reading a single pixel
         * that avoids the relatively high cost of flushing primitives
         * to be drawn on the GPU (considering how simple the geometry
         * is in this case) and then blocking on the long GPU pipelines
         * for the result.
         */
        if (_cogl_framebuffer_try_fast_read_pixel (framebuffer,
                x, y, source, format,
                pixels))
            return;
    }

    /* make sure any batched primitives get emitted to the GL driver
     * before issuing our read pixels...
     *
     * XXX: Note we currently use cogl_flush to ensure *all* journals
     * are flushed here and not _cogl_journal_flush because we don't
     * track the dependencies between framebuffers so we don't know if
     * the current framebuffer depends on the contents of other
     * framebuffers which could also have associated journal entries.
     */
    cogl_flush ();

    _cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (),
                                   framebuffer,
                                   COGL_FRAMEBUFFER_STATE_BIND);

    framebuffer_height = cogl_framebuffer_get_height (framebuffer);

    /* The y co-ordinate should be given in OpenGL's coordinate system
     * so 0 is the bottom row
     *
     * NB: all offscreen rendering is done upside down so no conversion
     * is necissary in this case.
     */
    if (!cogl_is_offscreen (framebuffer))
        y = framebuffer_height - y - height;

    /* Initialise the CoglBitmap */
    bpp = _cogl_get_format_bpp (format);
    bmp_format = format;

    if ((format & COGL_A_BIT))
    {
        /* We match the premultiplied state of the target buffer to the
         * premultiplied state of the framebuffer so that it will get
         * converted to the right format below */

        if ((framebuffer->format & COGL_PREMULT_BIT))
            bmp_format |= COGL_PREMULT_BIT;
        else
            bmp_format &= ~COGL_PREMULT_BIT;
    }

    bmp = _cogl_bitmap_new_from_data (pixels,
                                      bmp_format, width, height, rowstride,
                                      NULL, NULL);

    ctx->texture_driver->pixel_format_to_gl (format,
            &gl_intformat,
            &gl_format,
            &gl_type);

    /* NB: All offscreen rendering is done upside down so there is no need
     * to flip in this case... */
    if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_MESA_PACK_INVERT) &&
            !cogl_is_offscreen (framebuffer))
    {
        GE (ctx, glPixelStorei (GL_PACK_INVERT_MESA, TRUE));
        pack_invert_set = TRUE;
    }
    else
        pack_invert_set = FALSE;

    /* Under GLES only GL_RGBA with GL_UNSIGNED_BYTE as well as an
       implementation specific format under
       GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES and
       GL_IMPLEMENTATION_COLOR_READ_TYPE_OES is supported. We could try
       to be more clever and check if the requested type matches that
       but we would need some reliable functions to convert from GL
       types to Cogl types. For now, lets just always read in
       GL_RGBA/GL_UNSIGNED_BYTE and convert if necessary. We also need
       to use this intermediate buffer if the rowstride has padding
       because GLES does not support setting GL_ROW_LENGTH */
    if (ctx->driver != COGL_DRIVER_GL &&
            (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE ||
             rowstride != 4 * width))
    {
        CoglBitmap *tmp_bmp, *dst_bmp;
        guint8 *tmp_data = g_malloc (width * height * 4);

        tmp_bmp = _cogl_bitmap_new_from_data (tmp_data,
                                              COGL_PIXEL_FORMAT_RGBA_8888 |
                                              (bmp_format & COGL_PREMULT_BIT),
                                              width, height, 4 * width,
                                              (CoglBitmapDestroyNotify) g_free,
                                              NULL);

        ctx->texture_driver->prep_gl_for_pixels_download (4 * width, 4);

        GE( ctx, glReadPixels (x, y, width, height,
                               GL_RGBA, GL_UNSIGNED_BYTE,
                               tmp_data) );

        /* CoglBitmap doesn't currently have a way to convert without
           allocating its own buffer so we have to copy the data
           again */
        if ((dst_bmp = _cogl_bitmap_convert_format_and_premult (tmp_bmp,
                       format)))
        {
            _cogl_bitmap_copy_subregion (dst_bmp,
                                         bmp,
                                         0, 0,
                                         0, 0,
                                         width, height);
            cogl_object_unref (dst_bmp);
        }
        else
        {
            /* FIXME: there's no way to report an error here so we'll
               just have to leave the data initialised */
        }

        cogl_object_unref (tmp_bmp);
    }
    else
    {
        ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp);

        GE( ctx, glReadPixels (x, y, width, height, gl_format, gl_type, pixels) );

        /* Convert to the premult format specified by the caller
           in-place. This will do nothing if the premult status is already
           correct. */
        _cogl_bitmap_convert_premult_status (bmp, format);
    }

    /* Currently this function owns the pack_invert state and we don't want this
     * to interfere with other Cogl components so all other code can assume that
     * we leave the pack_invert state off. */
    if (pack_invert_set)
        GE (ctx, glPixelStorei (GL_PACK_INVERT_MESA, FALSE));

    /* NB: All offscreen rendering is done upside down so there is no need
     * to flip in this case... */
    if (!cogl_is_offscreen (framebuffer) && !pack_invert_set)
    {
        guint8 *temprow = g_alloca (rowstride * sizeof (guint8));

        /* vertically flip the buffer in-place */
        for (y = 0; y < height / 2; y++)
        {
            if (y != height - y - 1) /* skip center row */
            {
                memcpy (temprow,
                        pixels + y * rowstride, rowstride);
                memcpy (pixels + y * rowstride,
                        pixels + (height - y - 1) * rowstride, rowstride);
                memcpy (pixels + (height - y - 1) * rowstride,
                        temprow,
                        rowstride);
            }
        }
    }

    cogl_object_unref (bmp);
}