示例#1
0
static bool xenon360_gfx_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)
{
   gl_t *vid = data;

   ScreenUv[UV_TOP]	= ((float) (width) / (float) XE_W)*2;
   ScreenUv[UV_LEFT]	= ((float) (height) / (float) XE_H)*2;

   DrawVerticeFormats * Rect = Xe_VB_Lock(vid->gl_device, vid->vb, 0, 3 * sizeof(DrawVerticeFormats), XE_LOCK_WRITE);

   /* bottom left */
   Rect[1].v = ScreenUv[UV_LEFT];
   Rect[2].u = ScreenUv[UV_TOP];

   Xe_VB_Unlock(vid->gl_device, vid->vb);

   /* Refresh texture cache */
   uint16_t *dst       = Xe_Surface_LockRect(vid->gl_device, vid->g_pTexture, 0, 0, 0, 0, XE_LOCK_WRITE);
   const uint16_t *src = frame;
   unsigned stride_in  = pitch >>1;
   unsigned stride_out = vid->g_pTexture->wpitch >> 1;
   unsigned copy_size  = width << 1;

   for (unsigned y = 0; y < height; y++, dst += stride_out, src += stride_in)
      memcpy(dst, src, copy_size);
   Xe_Surface_Unlock(vid->gl_device, vid->g_pTexture);

   /* Reset states */
   Xe_InvalidateState(vid->gl_device);
   Xe_SetClearColor(vid->gl_device, 0);

   /* Select stream */
   Xe_SetTexture(vid->gl_device, 0, vid->g_pTexture);
   Xe_SetCullMode(vid->gl_device, XE_CULL_NONE);
   Xe_SetStreamSource(vid->gl_device, 0, vid->vb, 0, sizeof(DrawVerticeFormats));

   /* Select shaders */
   Xe_SetShader(vid->gl_device, SHADER_TYPE_PIXEL, vid->g_pPixelTexturedShader, 0);
   Xe_SetShader(vid->gl_device, SHADER_TYPE_VERTEX, vid->g_pVertexShader, 0);

#ifdef HAVE_MENU
   menu_driver_frame(video_info);
#endif

   /* Draw */
   Xe_DrawPrimitive(vid->gl_device, XE_PRIMTYPE_TRIANGLELIST, 0, 1);

   /* Resolve */
   Xe_Resolve(vid->gl_device);
   Xe_Sync(vid->gl_device);

   return true;
}
示例#2
0
static bool sdl2_gfx_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)
{
   sdl2_video_t *vid = (sdl2_video_t*)data;
   char title[128];

   if (vid->should_resize)
      sdl_refresh_viewport(vid);

   if (frame && video_info->libretro_running)
   {
      static struct retro_perf_counter sdl_copy_frame = {0};

      SDL_RenderClear(vid->renderer);
      sdl_refresh_input_size(vid, false, vid->video.rgb32, width, height, pitch);

      performance_counter_init(sdl_copy_frame, "sdl_copy_frame");
      performance_counter_start_plus(video_info->is_perfcnt_enable, sdl_copy_frame);

      SDL_UpdateTexture(vid->frame.tex, NULL, frame, pitch);

      performance_counter_stop_plus(video_info->is_perfcnt_enable, sdl_copy_frame);
   }

   SDL_RenderCopyEx(vid->renderer, vid->frame.tex, NULL, NULL, vid->rotation, NULL, SDL_FLIP_NONE);

#ifdef HAVE_MENU
   menu_driver_frame(video_info);
#endif

   if (vid->menu.active)
      SDL_RenderCopy(vid->renderer, vid->menu.tex, NULL, NULL);

   if (msg)
      sdl2_render_msg(vid, msg);

   SDL_RenderPresent(vid->renderer);

   title[0] = '\0';

   video_driver_get_window_title(title, sizeof(title));

   if (title[0])
      SDL_SetWindowTitle(vid->window, title);

   return true;
}
示例#3
0
static bool sdl2_gfx_frame(void *data, const void *frame, unsigned width,
                           unsigned height, unsigned pitch, const char *msg)
{
   char buf[128];
   sdl2_video_t *vid = (sdl2_video_t*)data;
   runloop_t *runloop = rarch_main_get_ptr();
   driver_t *driver = driver_get_ptr();

   if (vid->should_resize)
      sdl_refresh_viewport(vid);

   if (frame)
   {
      sdl_refresh_input_size(vid, false, vid->video.rgb32, width, height, pitch);

      RARCH_PERFORMANCE_INIT(sdl_copy_frame);
      RARCH_PERFORMANCE_START(sdl_copy_frame);

      SDL_UpdateTexture(vid->frame.tex, NULL, frame, pitch);

      RARCH_PERFORMANCE_STOP(sdl_copy_frame);
   }

   SDL_RenderCopyEx(vid->renderer, vid->frame.tex, NULL, NULL, vid->rotation, NULL, SDL_FLIP_NONE);

#ifdef HAVE_MENU
   if (runloop->is_menu)
      menu_driver_frame();
#endif

   if (vid->menu.active)
      SDL_RenderCopy(vid->renderer, vid->menu.tex, NULL, NULL);

   if (msg)
      sdl2_render_msg(vid, msg);

   SDL_RenderPresent(vid->renderer);

   if (video_monitor_get_fps(buf, sizeof(buf), NULL, 0))
      SDL_SetWindowTitle(vid->window, buf);

   vid->frame_count++;

   return true;
}
示例#4
0
static bool vita2d_gfx_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)
{
   void *tex_p;
   vita_video_t *vita = (vita_video_t *)data;

   if (frame)
   {
      if(!(vita->texture&&vita2d_texture_get_datap(vita->texture)==frame))
      {
         unsigned i;
         unsigned int stride;

         if ((width != vita->width || height != vita->height) && vita->texture)
         {
            vita2d_free_texture(vita->texture);
            vita->texture = NULL;
         }

         if (!vita->texture)
         {
            RARCH_LOG("Creating texture: %ix%i\n", width, height);
            vita->width = width;
            vita->height = height;
            vita->texture = vita2d_create_empty_texture_format(width, height, vita->format);
            vita2d_texture_set_filters(vita->texture,vita->tex_filter,vita->tex_filter);
         }
         tex_p = vita2d_texture_get_datap(vita->texture);
         stride = vita2d_texture_get_stride(vita->texture);

         if (vita->format == SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1RGB)
         {
            stride                     /= 4;
            pitch                      /= 4;
            uint32_t             *tex32 = tex_p;
            const uint32_t     *frame32 = frame;

            for (i = 0; i < height; i++)
               memcpy_neon(&tex32[i*stride],&frame32[i*pitch],pitch*sizeof(uint32_t));
         }
         else
         {
            stride                 /= 2;
            pitch                  /= 2;
            uint16_t *tex16         = tex_p;
            const uint16_t *frame16 = frame;

            for (i = 0; i < height; i++)
               memcpy_neon(&tex16[i*stride],&frame16[i*pitch],width*sizeof(uint16_t));
         }
      }
   }

   if (vita->should_resize)
      vita2d_gfx_update_viewport(vita);

   vita2d_start_drawing();

   vita2d_draw_rectangle(0,0,PSP_FB_WIDTH,PSP_FB_HEIGHT,vita2d_get_clear_color());

   if (vita->texture)
   {
      if (vita->fullscreen)
         vita2d_draw_texture_scale(vita->texture,
               0, 0,
               PSP_FB_WIDTH  / (float)vita->width,
               PSP_FB_HEIGHT / (float)vita->height);
      else
      {
         const float radian = 90 * 0.0174532925f;
         const float rad = vita->rotation * radian;
         float scalex = vita->vp.width / (float)vita->width;
         float scaley = vita->vp.height / (float)vita->height;
         vita2d_draw_texture_scale_rotate(vita->texture,vita->vp.x,
               vita->vp.y, scalex, scaley, rad);
      }
   }

#ifdef HAVE_OVERLAY
   if (vita->overlay_enable)
      vita2d_render_overlay(vita);
#endif

   if (vita->menu.active)
   {
#ifdef HAVE_MENU
      menu_driver_frame(video_info);
#endif

      if(vita->menu.texture)
      {
         if (vita->fullscreen)
            vita2d_draw_texture_scale(vita->menu.texture,
                  0, 0,
                  PSP_FB_WIDTH  / (float)vita->menu.width,
                  PSP_FB_HEIGHT / (float)vita->menu.height);
         else
         {
            if (vita->menu.width > vita->menu.height)
            {
               float scale = PSP_FB_HEIGHT / (float)vita->menu.height;
               float w = vita->menu.width * scale;
               vita2d_draw_texture_scale(vita->menu.texture,
                     PSP_FB_WIDTH / 2.0f - w/2.0f, 0.0f,
                     scale, scale);
            }
            else
            {
               float scale = PSP_FB_WIDTH / (float)vita->menu.width;
               float h = vita->menu.height * scale;
               vita2d_draw_texture_scale(vita->menu.texture,
                     0.0f, PSP_FB_HEIGHT / 2.0f - h/2.0f,
                     scale, scale);
            }
         }
      }
   }

   if(!string_is_empty(msg))
      font_driver_render_msg(video_info, NULL, msg, NULL);

   vita2d_end_drawing();
   vita2d_swap_buffers();

   return true;
}
示例#5
0
static bool psp_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)
{
#ifdef DISPLAY_FPS
   uint32_t diff;
   static uint64_t currentTick,lastTick;
   static int frames;
   static float fps                        = 0.0;
#endif
   psp1_video_t *psp                       = (psp1_video_t*)data;

   if (!width || !height)
      return false;

   if (((uint32_t)frame&0x04000000) || (frame == RETRO_HW_FRAME_BUFFER_VALID))
      psp->hw_render = true;
   else if (frame)
      psp->hw_render = false;

   if (!psp->hw_render)
      sceGuSync(0, 0); /* let the core decide when to sync when HW_RENDER */

   pspDebugScreenSetBase(psp->draw_buffer);

   pspDebugScreenSetXY(0,0);

   if (video_info->fps_show)
   {
      pspDebugScreenSetXY(68 - strlen(video_info->fps_text) - 1,0);
      pspDebugScreenPuts(video_info->fps_text);
      pspDebugScreenSetXY(0,1);
   }

   if (msg)
      pspDebugScreenPuts(msg);

   if ((psp->vsync)&&(psp->vblank_not_reached))
      sceDisplayWaitVblankStart();

   psp->vblank_not_reached = true;

#ifdef DISPLAY_FPS
   frames++;
   sceRtcGetCurrentTick(&currentTick);
   diff = currentTick - lastTick;
   if(diff > 1000000)
   {
      fps = (float)frames * 1000000.0 / diff;
      lastTick = currentTick;
      frames = 0;
   }

   pspDebugScreenSetXY(0,0);
   pspDebugScreenPrintf("%f", fps);
#endif

   psp->draw_buffer = FROM_GU_POINTER(sceGuSwapBuffers());

   if (psp->should_resize)
      psp_update_viewport(psp, video_info);

   psp_set_tex_coords(psp->frame_coords, width, height);

   sceGuStart(GU_DIRECT, psp->main_dList);

   sceGuTexFilter(psp->tex_filter, psp->tex_filter);
   sceGuClear(GU_COLOR_BUFFER_BIT);

   /* frame in VRAM ? texture/palette was 
    * set in core so draw directly */
   if (psp->hw_render) 
      sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | 
            GU_TRANSFORM_2D, PSP_FRAME_VERTEX_COUNT, NULL,
            (void*)(psp->frame_coords));
   else
   {
      if (frame)
      {
         sceKernelDcacheWritebackRange(frame,pitch * height);
         sceGuCopyImage(psp->rgb32? GU_PSM_8888 : GU_PSM_5650, ((u32)frame & 0xF) >> psp->bpp_log2,
               0, width, height, pitch >> psp->bpp_log2,
               (void*)((u32)frame & ~0xF), 0, 0, width, psp->texture);
      }
      sceGuTexImage(0, next_pow2(width), next_pow2(height), width, psp->texture);
      sceGuCallList(psp->frame_dList);
   }

   sceGuFinish();

#ifdef HAVE_MENU
   menu_driver_frame(video_info);
#endif

   if(psp->menu.active)
   {
      sceGuSendList(GU_TAIL, psp->menu.dList, &(psp->menu.context_storage));
      sceGuSync(0, 0);
   }

   return true;
}
示例#6
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;
}
示例#7
0
文件: gl1.c 项目: leiradel/RetroArch
static bool gl1_gfx_frame(void *data, const void *frame,
      unsigned frame_width, unsigned frame_height, uint64_t frame_count,
      unsigned pitch, const char *msg, video_frame_info_t *video_info)
{
   gfx_ctx_mode_t mode;
   const void *frame_to_copy = NULL;
   unsigned width            = 0;
   unsigned height           = 0;
   unsigned bits             = gl1_video_bits;
   bool draw                 = true;
   gl1_t *gl1                = (gl1_t*)data;
   unsigned pot_width        = 0;
   unsigned pot_height       = 0;

   gl1_context_bind_hw_render(gl1, false);

   /* FIXME: Force these settings off as they interfere with the rendering */
   video_info->xmb_shadows_enable   = false;
   video_info->menu_shader_pipeline = 0;

   if (!frame || !frame_width || !frame_height)
      return true;

   if (gl1->should_resize)
   {
      gfx_ctx_mode_t mode;

      gl1->should_resize = false;

      mode.width        = width;
      mode.height       = height;

      video_info->cb_set_resize(video_info->context_data,
            mode.width, mode.height);

      gl1_gfx_set_viewport(gl1, video_info, video_info->width, video_info->height, false, true);
   }

   glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
   glClear(GL_COLOR_BUFFER_BIT);

   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   if (  gl1_video_width  != frame_width  ||
         gl1_video_height != frame_height ||
         gl1_video_pitch  != pitch)
   {
      if (frame_width > 4 && frame_height > 4)
      {
         gl1_video_width  = frame_width;
         gl1_video_height = frame_height;
         gl1_video_pitch  = pitch;

         pot_width = get_pot(frame_width);
         pot_height = get_pot(frame_height);

         if (gl1_video_buf)
            free(gl1_video_buf);

         gl1_video_buf = (unsigned char*)malloc(pot_width * pot_height * 4);
      }
   }

   width         = gl1_video_width;
   height        = gl1_video_height;
   pitch         = gl1_video_pitch;

   pot_width = get_pot(width);
   pot_height = get_pot(height);

   if (  frame_width  == 4 &&
         frame_height == 4 &&
         (frame_width < width && frame_height < height)
      )
      draw = false;

   if (draw && gl1_video_buf)
   {
      if (bits == 32)
      {
         unsigned y;
         /* copy lines into top-left portion of larger (power-of-two) buffer */
         for (y = 0; y < height; y++)
            memcpy(gl1_video_buf + ((pot_width * (bits / 8)) * y), (const unsigned char*)frame + (pitch * y), width * (bits / 8));
      }
      else if (bits == 16)
         conv_rgb565_argb8888(gl1_video_buf, frame, width, height, pot_width * sizeof(unsigned), pitch);

      frame_to_copy = gl1_video_buf;
   }

   if (gl1->video_width != width || gl1->video_height != height)
   {
      gl1->video_width  = width;
      gl1->video_height = height;
   }

   video_context_driver_get_video_size(&mode);

   gl1->screen_width           = mode.width;
   gl1->screen_height          = mode.height;

   if (draw)
   {
      if (frame_to_copy)
      {
         draw_tex(gl1, pot_width, pot_height, width, height, gl1->tex, frame_to_copy);
      }
   }

   if (gl1_menu_frame && video_info->menu_is_alive)
   {
      frame_to_copy = NULL;
      width         = gl1_menu_width;
      height        = gl1_menu_height;
      pitch         = gl1_menu_pitch;
      bits          = gl1_menu_bits;

      pot_width = get_pot(width);
      pot_height = get_pot(height);

      if (gl1_menu_size_changed)
      {
         gl1_menu_size_changed = false;

         if (gl1_menu_video_buf)
         {
            free(gl1_menu_video_buf);
            gl1_menu_video_buf = NULL;
         }
      }

      if (!gl1_menu_video_buf)
         gl1_menu_video_buf = (unsigned char*)malloc(pot_width * pot_height * 4);

      if (bits == 16 && gl1_menu_video_buf)
      {
         conv_rgba4444_argb8888(gl1_menu_video_buf, gl1_menu_frame, width, height, pot_width * sizeof(unsigned), pitch);

         frame_to_copy = gl1_menu_video_buf;

         if (gl1->menu_texture_full_screen)
         {
            glViewport(0, 0, video_info->width, video_info->height);
            draw_tex(gl1, pot_width, pot_height, width, height, gl1->menu_tex, frame_to_copy);
            glViewport(gl1->vp.x, gl1->vp.y, gl1->vp.width, gl1->vp.height);
         }
         else
            draw_tex(gl1, pot_width, pot_height, width, height, gl1->menu_tex, frame_to_copy);
      }
   }

#ifdef HAVE_MENU
   if (gl1->menu_texture_enable)
      menu_driver_frame(video_info);
   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);
#if 0
         osd_params->y               = 0.350f;
         osd_params->scale           = 0.75f;
         font_driver_render_msg(video_info, NULL, video_info->chat_text,
               (const struct font_params*)&video_info->osd_stat_params);
#endif
      }
   }

#ifdef HAVE_MENU_WIDGETS
   menu_widgets_frame(video_info);
#endif
#endif

#ifdef HAVE_OVERLAY
   if (gl1->overlay_enable)
      gl1_render_overlay(gl1, video_info);
#endif

   if (msg)
      font_driver_render_msg(video_info, NULL, msg, NULL);

   video_info->cb_update_window_title(
         video_info->context_data, video_info);

   /* Screenshots. */
   if (gl1->readback_buffer_screenshot)
      gl1_readback(gl1,
            4, GL_RGBA, GL_UNSIGNED_BYTE,
            gl1->readback_buffer_screenshot);

   /* emscripten has to do black frame insertion in its main loop */
#ifndef EMSCRIPTEN
   /* Disable BFI during fast forward, slow-motion,
    * and pause to prevent flicker. */
   if (
         video_info->black_frame_insertion
         && !video_info->input_driver_nonblock_state
         && !video_info->runloop_is_slowmotion
         && !video_info->runloop_is_paused)
   {
      video_info->cb_swap_buffers(video_info->context_data, video_info);
      glClear(GL_COLOR_BUFFER_BIT);
   }
#endif

   video_info->cb_swap_buffers(video_info->context_data, video_info);

   /* check if we are fast forwarding or in menu, if we are ignore hard sync */
   if (video_info->hard_sync
         && !video_info->input_driver_nonblock_state
         && !gl1->menu_texture_enable)
   {
      glClear(GL_COLOR_BUFFER_BIT);
      glFinish();
   }

   gl1_context_bind_hw_render(gl1, true);

   return true;
}
示例#8
0
文件: gdi_gfx.c 项目: Zarh/RetroArch
static bool gdi_gfx_frame(void *data, const void *frame,
      unsigned frame_width, unsigned frame_height, uint64_t frame_count,
      unsigned pitch, const char *msg, video_frame_info_t *video_info)
{
   gfx_ctx_mode_t mode;
   const void *frame_to_copy = frame;
   unsigned width            = 0;
   unsigned height           = 0;
   unsigned bits             = gdi_video_bits;
   bool draw                 = true;
   gdi_t *gdi                = (gdi_t*)data;
   HWND hwnd                 = win32_get_window();

   if (!frame || !frame_width || !frame_height)
      return true;

#ifdef HAVE_MENU
   menu_driver_frame(video_info);
#endif

   if (gdi_video_width != frame_width || gdi_video_height != frame_height || gdi_video_pitch != pitch)
   {
      if (frame_width > 4 && frame_height > 4)
      {
         gdi_video_width = frame_width;
         gdi_video_height = frame_height;
         gdi_video_pitch = pitch;
      }
   }

   if (gdi_menu_frame && video_info->menu_is_alive)
   {
      frame_to_copy = gdi_menu_frame;
      width         = gdi_menu_width;
      height        = gdi_menu_height;
      pitch         = gdi_menu_pitch;
      bits          = gdi_menu_bits;
   }
   else
   {
      width         = gdi_video_width;
      height        = gdi_video_height;
      pitch         = gdi_video_pitch;

      if (frame_width == 4 && frame_height == 4 && (frame_width < width && frame_height < height))
         draw = false;

      if (video_info->menu_is_alive)
         draw = false;
   }

   if (hwnd && !gdi->winDC)
   {
      gdi->winDC = GetDC(hwnd);
      gdi->memDC = CreateCompatibleDC(gdi->winDC);
      gdi->video_width = width;
      gdi->video_height = height;
      gdi->bmp = CreateCompatibleBitmap(gdi->winDC, gdi->video_width, gdi->video_height);
   }

   gdi->bmp_old  = (HBITMAP)SelectObject(gdi->memDC, gdi->bmp);

   if (gdi->video_width != width || gdi->video_height != height)
   {
      SelectObject(gdi->memDC, gdi->bmp_old);
      DeleteObject(gdi->bmp);

      gdi->video_width = width;
      gdi->video_height = height;
      gdi->bmp = CreateCompatibleBitmap(gdi->winDC, gdi->video_width, gdi->video_height);
      gdi->bmp_old = (HBITMAP)SelectObject(gdi->memDC, gdi->bmp);
   }

   video_context_driver_get_video_size(&mode);

   gdi->screen_width = mode.width;
   gdi->screen_height = mode.height;

   BITMAPINFO *info = (BITMAPINFO*)calloc(1, sizeof(*info) + (3 * sizeof(RGBQUAD)));

   info->bmiHeader.biBitCount  = bits;
   info->bmiHeader.biWidth     = pitch / (bits / 8);
   info->bmiHeader.biHeight    = -height;
   info->bmiHeader.biPlanes    = 1;
   info->bmiHeader.biSize      = sizeof(BITMAPINFOHEADER);
   info->bmiHeader.biSizeImage = 0;

   if (bits == 16)
   {
      unsigned *masks = (unsigned*)info->bmiColors;

      info->bmiHeader.biCompression = BI_BITFIELDS;

      /* default 16-bit format on Windows is XRGB1555 */
      if (frame_to_copy == gdi_menu_frame)
      {
         /* map RGB444 color bits for RGUI */
         masks[0] = 0xF000;
         masks[1] = 0x0F00;
         masks[2] = 0x00F0;
      }
      else
      {
         /* map RGB565 color bits for core */
         masks[0] = 0xF800;
         masks[1] = 0x07E0;
         masks[2] = 0x001F;
      }
   }
   else
      info->bmiHeader.biCompression = BI_RGB;

   if (draw)
   {
      StretchDIBits(gdi->memDC, 0, 0, width, height, 0, 0, width, height,
            frame_to_copy, info, DIB_RGB_COLORS, SRCCOPY);
   }

   SelectObject(gdi->memDC, gdi->bmp_old);

   free(info);

   if (msg)
      font_driver_render_msg(video_info, NULL, msg, NULL);

   InvalidateRect(hwnd, NULL, false);

   video_info->cb_update_window_title(
         video_info->context_data, video_info);

   return true;
}
示例#9
0
static bool caca_gfx_frame(void *data, const void *frame,
      unsigned frame_width, unsigned frame_height, uint64_t frame_count,
      unsigned pitch, const char *msg, video_frame_info_t *video_info)
{
   size_t len = 0;
   void *buffer = NULL;
   const void *frame_to_copy = frame;
   unsigned width = 0;
   unsigned height = 0;
   bool draw = true;

   (void)data;
   (void)frame;
   (void)frame_width;
   (void)frame_height;
   (void)pitch;
   (void)msg;

   if (!frame || !frame_width || !frame_height)
      return true;

   if (  caca_video_width  != frame_width   ||
         caca_video_height != frame_height  ||
         caca_video_pitch  != pitch)
   {
      if (frame_width > 4 && frame_height > 4)
      {
         caca_video_width = frame_width;
         caca_video_height = frame_height;
         caca_video_pitch = pitch;
         caca_gfx_free(NULL);
         caca_gfx_create();
      }
   }

   if (!caca_cv)
      return true;

   if (caca_menu_frame && video_info->menu_is_alive)
      frame_to_copy = caca_menu_frame;

   width = caca_get_canvas_width(caca_cv);
   height = caca_get_canvas_height(caca_cv);

   if (  frame_to_copy == frame &&
         frame_width   == 4 &&
         frame_height  == 4 &&
         (frame_width < width && frame_height < height))
      draw = false;

   if (video_info->menu_is_alive)
      draw = false;

   caca_clear_canvas(caca_cv);

#ifdef HAVE_MENU
   menu_driver_frame(video_info);
#endif

   if (msg)
      font_driver_render_msg(video_info, NULL, msg, NULL);

   if (draw)
   {
      caca_dither_bitmap(caca_cv, 0, 0,
            width,
            height,
            caca_dither, frame_to_copy);

      buffer = caca_export_canvas_to_memory(caca_cv, "caca", &len);

      if (buffer)
      {
         if (len)
            caca_refresh_display(caca_display);

         free(buffer);
      }
   }

   return true;
}