//Link a framebuffer to a surface in the current context
static void attach_surface(EGLDisplay display, struct context *current, struct surface *surface)
{
   if(!surface->buffer)
   {
       //An attached surface must have a buffer
       surface_dequeue_buffer(surface);

       LOGV("attach_surface - 1" );

       if(surface->buffer)
       {
         LOGV("attach_surface - 2" );

         attach_buffer( display, surface );

         //yay
         LOGV("attach_surface - 3 (yay)" );
       }
       else
       {
           LOGV("attach_surface() Failed to dequeue buffer: surface = %p, Thread = %d",
               surface,
               gettid());
       }
   }
   else
   {
      LOGV("attach_surface() - already got buffer, so we are happy: surface  = %p, Thread = %d",
               surface,
               gettid());
   }

    surface->made_current = 1;
}
Пример #2
0
static bool switch_frame(void *data, const void *frame,
      unsigned width, unsigned height,
      uint64_t frame_count, unsigned pitch,
      const char *msg, video_frame_info_t *video_info)
{
	static uint64_t last_frame = 0;
	
   unsigned x, y;
   result_t r;
   int tgtw, tgth, centerx, centery;
   uint32_t *out_buffer   = NULL;
   switch_video_t *sw     = data;
   int xsf                = 1280 / width;
   int ysf                = 720  / height;
   int sf                 = xsf;

   if (ysf < sf)
      sf = ysf;

   tgtw                   = width * sf;
   tgth                   = height * sf;
   centerx                = (1280-tgtw)/2;
   centery                = (720-tgth)/2;

   // clear image to black
   for(y = 0; y < 720; y++)
   {
      for(x = 0; x < 1280; x++)
      {
         sw->image[y*1280+x] = 0xFF000000;
      }
   }

   if(width > 0 && height > 0) {
	   if(sw->last_width != width ||
	      sw->last_height != height)
		   {
			   scaler_ctx_gen_reset(&sw->scaler);
			   
			   sw->scaler.in_width = width;
			   sw->scaler.in_height = height;
			   sw->scaler.in_stride = pitch;
			   sw->scaler.in_fmt = sw->rgb32 ? SCALER_FMT_ARGB8888 : SCALER_FMT_RGB565;
			   
			   sw->scaler.out_width = tgtw;
			   sw->scaler.out_height = tgth;
			   sw->scaler.out_stride = 1280 * sizeof(uint32_t);
			   sw->scaler.out_fmt = SCALER_FMT_ABGR8888;
			   
			   sw->scaler.scaler_type = SCALER_TYPE_POINT;
			   
			   if(!scaler_ctx_gen_filter(&sw->scaler)) {
				   RARCH_ERR("failed to generate scaler for main image\n");
				   return false;
			   }

			   sw->last_width = width;
			   sw->last_height = height;
		   }

	   scaler_ctx_scale(&sw->scaler, sw->image + (centery * 1280) + centerx, frame);
   }

#if defined(HAVE_MENU)
   if (sw->menu_texture.enable)
	{
		menu_driver_frame(video_info);

		if (sw->menu_texture.pixels)
		{
#if 0
			if (sw->menu_texture.fullscreen)
         {
#endif
	         scaler_ctx_scale(&sw->menu_texture.scaler, sw->image +
	                          ((720-sw->menu_texture.tgth)/2)*1280 +
	                          ((1280-sw->menu_texture.tgtw)/2), sw->menu_texture.pixels);
#if 0
         }
         else
         {
         }
#endif
		}
	}
   else if (video_info->statistics_show)
   {
      struct font_params *osd_params = (struct font_params*)
         &video_info->osd_stat_params;

      if (osd_params)
      {
         font_driver_render_msg(video_info, NULL, video_info->stat_text,
               (const struct font_params*)&video_info->osd_stat_params);
      }
   }
#endif

#if 0
   if (frame_count > 6000)
   {
      display_finalize();
      exit(0);
   }
#endif

   if (msg && strlen(msg) > 0)
      RARCH_LOG("message: %s\n", msg);

   r = surface_dequeue_buffer(&sw->surface, &out_buffer);
   if (sw->vsync)
	   switch_wait_vsync(sw);
   svcSleepThread(10000);
   if(r != RESULT_OK) {
	   return true; // just skip the frame
   }
   
   gfx_slow_swizzling_blit(out_buffer, sw->image, 1280, 720, 0, 0);
   
   r = surface_queue_buffer(&sw->surface);
   
   if (r != RESULT_OK)
      return false;

   last_frame = svcGetSystemTick();
   return true;
}
EGLBoolean eglSwapBuffers(EGLDisplay display, EGLSurface surface_)
{
    struct context *current_context = brcm_egl_get_current();
    struct surface *surface = (struct surface *)surface_;

    if( !current_context )
    {
       LOGE("eglSwapBuffers() - TODO - function called but no current context is valid");
	   return false;
    }

    //nothing bound?
    if(surface_ == EGL_NO_SURFACE)
    {
        LOGE("eglSwapBuffers(%p) error: EGL_BAD_SURFACE Thread: %d", current_context, gettid());
        return EGL_FALSE;
    }

    //do we have an android native window already assigned to our egl context?
    if(surface->window)
    {

        //check that the context wasn't deleted
        //TODO - explain why this could occur
#if 0
        if(egl_is_context_lost(thread))
        {
            thread->error = EGL_CONTEXT_LOST;
            LOGE("eglSwapBuffers(%p) error: EGL_CONTEXT_LOST, Thread: %d", current_context, gettid());
            return EGL_FALSE;
        }
#endif

        LOGD_IF(current_context->profiling, "eglSwapBuffers(%d, %p) %d", (int)display, (void *)surface, gettid());

        //todo - add in invalidates here
#ifndef BRCM_V3D_OPT
        glFinish();
#else
        glFinish();
        glFlush();
		if(surface->buffer->format == HAL_PIXEL_FORMAT_YCbCr_422_I)
			convert_to_yuv(current_context->composer,surface->buffer);
#endif
        //TODO - if we don't get a buffer below, then v3d will have a pointer to memory that it can't write to anymore

		EGLint res = glGetError();
		if (res == GL_OUT_OF_MEMORY)
			{
			LOGE("eglSwapBuffers Error 0x%x",res);
			return false;
			}
        //send the current buffer out
        surface_enqueue_buffer( surface);

		sync_composer(current_context->composer);

        //grab a new buffer and bind it to V3D
        if( !surface_dequeue_buffer(surface) )
           LOGE("surface_dequeue_buffer FATAL error - no buffer to attach");

         attach_buffer(display, surface);

        return EGL_TRUE;
    }
    else
    {
       LOGE("eglSwapBuffers called but no window bound!" );
    }
    return EGL_FALSE;
}