예제 #1
0
/* gfx_gdi_lock:
 */
static void gfx_gdi_lock(struct BITMAP *bmp)
{
   /* to prevent the drawing threads and the rendering proc
    * from concurrently accessing the dirty lines array
    */
   _enter_gfx_critical();

   /* arrange for drawing requests to pause when we are in the background */
   if (!_win_app_foreground) {
      /* stop timer */
      remove_int(render_proc);

      _exit_gfx_critical();

      if (GFX_CRITICAL_RELEASED)
         _win_thread_switch_out();

      _enter_gfx_critical();

      /* restart timer */
      install_int(render_proc, RENDER_DELAY);
   }

   lock_nesting++;
   bmp->id |= BMP_ID_LOCKED;
}
예제 #2
0
파일: wddbmpl.c 프로젝트: 4144/aseprite
/* unregister_ddraw_surface:
 *  Removes a surface from the linked list.
 */
void unregister_ddraw_surface(DDRAW_SURFACE *surf)
{
   DDRAW_SURFACE *item;

   _enter_gfx_critical();

   item = ddraw_surface_list;

   while (item) {
      if (item == surf) {
         /* surface found, unlink now */
         if (item->next)
            item->next->prev = item->prev;
         if (item->prev)
            item->prev->next = item->next;
         if (ddraw_surface_list == item)
            ddraw_surface_list = item->next;

         item->next = NULL;
         item->prev = NULL;
         break;
      }

      item = item->next;
   }

   _exit_gfx_critical();
}
예제 #3
0
/* ddraw_do_stretch_blit:
 *   Accelerated stretch_blit, stretch_sprite, stretch_masked_blit
 */
static void ddraw_do_stretch_blit(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)
{
   RECT dest_rect, source_rect;
   DDCOLORKEY src_key;
   HRESULT hr;
   BITMAP *dest_parent;
   BITMAP *source_parent;

   dest_rect.left = dest_x + dest->x_ofs;
   dest_rect.top = dest_y + dest->y_ofs;
   dest_rect.right = dest_x + dest->x_ofs + dest_width;
   dest_rect.bottom = dest_y + dest->y_ofs + dest_height;

   source_rect.left = source_x + source->x_ofs;
   source_rect.top = source_y + source->y_ofs;
   source_rect.right = source_x + source->x_ofs + source_width;
   source_rect.bottom = source_y + source->y_ofs + source_height;

   src_key.dwColorSpaceLowValue = source->vtable->mask_color;
   src_key.dwColorSpaceHighValue = source->vtable->mask_color;

   if ( ( (masked && (gfx_capabilities & GFX_HW_VRAM_STRETCH_BLIT_MASKED)) ||
          (!masked && (gfx_capabilities & GFX_HW_VRAM_STRETCH_BLIT)) 
        ) && ( is_video_bitmap(source) || is_system_bitmap(source) ) ) {

      /* find parents */
      dest_parent = dest;
      while (dest_parent->id & BMP_ID_SUB)
         dest_parent = (BITMAP *)dest_parent->extra;

      source_parent = source;
      while (source_parent->id & BMP_ID_SUB)
         source_parent = (BITMAP *)source_parent->extra;

      _enter_gfx_critical();
      gfx_directx_release_lock(dest);
      gfx_directx_release_lock(source);

      IDirectDrawSurface2_SetColorKey(DDRAW_SURFACE_OF(source_parent)->id,
                                      DDCKEY_SRCBLT, &src_key);

      hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(dest_parent)->id, &dest_rect,
                                   DDRAW_SURFACE_OF(source_parent)->id, &source_rect,
                                   (masked ? DDBLT_KEYSRC : 0) | DDBLT_WAIT, NULL);
      _exit_gfx_critical();

      if (FAILED(hr))
	 _TRACE(PREFIX_E "Blt failed (%x)\n", hr);

      /* only for windowed mode */
      if ((gfx_driver->id == GFX_DIRECTX_WIN) && (dest_parent == gfx_directx_forefront_bitmap))
         win_gfx_driver->paint(&dest_rect);
   }
   else {
      /* have to use the original software version */
      _orig_stretch_blit(source, dest, source_x, source_y, source_width, source_height, dest_x, dest_y, dest_width, dest_height, masked);
   }
}
예제 #4
0
/* gfx_directx_switch_out:
 *  Arranges for drawing requests to pause when we are in the background.
 */
static void gfx_directx_switch_out(void)
{
   _exit_gfx_critical();

   if (GFX_CRITICAL_RELEASED)
      _win_thread_switch_out();

   _enter_gfx_critical();
}
예제 #5
0
/* restore_all_ddraw_surfaces:
 *  Restores all the surfaces. Returns 0 on success or -1 on failure,
 *  in which case restoring is stopped at the first failure.
 */
int restore_all_ddraw_surfaces(void)
{
   DDRAW_SURFACE *item = ddraw_surface_list;

   _enter_gfx_critical();

   while (item) {
      if (gfx_directx_restore_surface(item) != 0) {
         _exit_gfx_critical();
         return -1;
      }
      item = item->next;
   }

   _exit_gfx_critical();

   _TRACE(PREFIX_I "all DirectDraw surfaces restored\n");

   return 0;
}
예제 #6
0
/* gfx_gdi_unlock:
 */
static void gfx_gdi_unlock(struct BITMAP *bmp)
{
   if (lock_nesting > 0) {
      lock_nesting--;

      if (!lock_nesting)
         bmp->id &= ~BMP_ID_LOCKED;

      _exit_gfx_critical();
   }
}
예제 #7
0
/* gfx_gdi_set_palette:
 */
static void gfx_gdi_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync)
{
   int c;

   for (c=from; c<=to; c++)
      palette[c] = p[c];

   /* invalidate the whole screen */
   _enter_gfx_critical();
   gdi_dirty_lines[0] = gdi_dirty_lines[gfx_gdi.h-1] = 1;
   _exit_gfx_critical();
}
예제 #8
0
파일: wddbmpl.c 프로젝트: 4144/aseprite
/* register_ddraw_surface:
 *  Adds a surface to the linked list.
 */
void register_ddraw_surface(DDRAW_SURFACE *surf)
{
   _enter_gfx_critical();

   surf->next = ddraw_surface_list;
   surf->prev = NULL;

   if (ddraw_surface_list)
      ddraw_surface_list->prev = surf;

   ddraw_surface_list = surf;

   _exit_gfx_critical();
}
예제 #9
0
/* restore_all_ddraw_surfaces:
 *  Restores all the surfaces. Returns 0 on success or -1 on failure,
 *  in which case restoring is stopped at the first failure.
 */
int restore_all_ddraw_surfaces(void)
{
   DDRAW_SURFACE *item = ddraw_surface_list;
   HRESULT hr;

   _enter_gfx_critical();

   while (item) {
      hr = IDirectDrawSurface2_Restore(item->id);
      if (FAILED(hr)) {
         _exit_gfx_critical();
         return -1;
      }

      item = item->next;
   }

   _exit_gfx_critical();

   _TRACE(PREFIX_I "all DirectDraw surfaces restored\n");

   return 0;
}
예제 #10
0
/* gdi_update_window:
 *  Updates the window.
 */
static void gdi_update_window(RECT *rect)
{
   HDC hdc;
   HWND allegro_wnd = win_get_window();

   _enter_gfx_critical();

   if (!gdi_screen) {
      _exit_gfx_critical();
      return;
   }

   hdc = GetDC(allegro_wnd);

   if (_color_depth == 8)
      set_palette_to_hdc(hdc, palette);

   blit_to_hdc(gdi_screen, hdc, rect->left, rect->top, rect->left, rect->top,
               rect->right - rect->left, rect->bottom - rect->top);

   ReleaseDC(allegro_wnd, hdc);

   _exit_gfx_critical();
}
예제 #11
0
/* gfx_directx_autolock:
 *  Locks the surface and prepares the lines array of the bitmap.
 *  This version is used directly by the bank switch functions, ie.
 *  it handles the autolocking mode, rather than being called directly.
 */
void gfx_directx_autolock(BITMAP *bmp)
{
   DDRAW_SURFACE *surf;
   BITMAP *parent;
   int pitch;
   unsigned char *data;
   int y;

   if (bmp->id & BMP_ID_SUB) {
      /* if it's a sub-bitmap, start by locking our parent */
      parent = (BITMAP *)bmp->extra;
      gfx_directx_autolock(parent);
      bmp->id |= BMP_ID_LOCKED;
      if (parent->id & BMP_ID_AUTOLOCK) {
         bmp->id |= BMP_ID_AUTOLOCK;
         parent->id &= ~BMP_ID_AUTOLOCK;
      }

      /* update the line array if our parent has moved */
      pitch = (long)parent->line[1] - (long)parent->line[0];
      data = parent->line[0] +
             (bmp->y_ofs - parent->y_ofs) * pitch +
             (bmp->x_ofs - parent->x_ofs) * BYTES_PER_PIXEL(bitmap_color_depth(bmp));

      if (data != bmp->line[0]) {
         for (y = 0; y < bmp->h; y++) {
            bmp->line[y] = data;
            data += pitch;
         }
      }
   }
   else {
      /* this is a real bitmap, so can be locked directly */
      surf = DDRAW_SURFACE_OF(bmp);

      if (surf->lock_nesting) {
         /* re-locking after a hwaccel, so don't change nesting state */
         gfx_directx_lock(bmp);
         surf->lock_nesting--;
         _exit_gfx_critical();
      }
      else {
         /* locking for the first time */
         gfx_directx_lock(bmp);
         bmp->id |= BMP_ID_AUTOLOCK;
      }
   }
}
예제 #12
0
/* gfx_gdi_exit:
 */
static void gfx_gdi_exit(struct BITMAP *bmp)
{
   _enter_critical();

   _enter_gfx_critical();

   if (bmp) {
      save_window_pos();
      clear_bitmap(bmp);
   }

   /* stop timer */
   remove_int(render_proc);
   CloseHandle(vsync_event);

   /* disconnect from the system driver */
   win_gfx_driver = NULL;

   /* destroy dirty lines array */   
   _AL_FREE(gdi_dirty_lines);
   gdi_dirty_lines = NULL;   

   /* destroy screen surface */
   _AL_FREE(screen_surf);
   gdi_screen = NULL;

   /* destroy mouse bitmaps */
   if (wgdi_mouse_sprite) {
      destroy_bitmap(wgdi_mouse_sprite);
      wgdi_mouse_sprite = NULL;

      destroy_bitmap(mouse_frontbuffer);
      mouse_frontbuffer = NULL;

      destroy_bitmap(mouse_backbuffer);
      mouse_backbuffer = NULL;
   }

   _exit_gfx_critical();

   /* before restoring video mode, hide window */
   set_display_switch_mode(SWITCH_PAUSE);
   system_driver->restore_console_state();
   restore_window_style();

   _exit_critical();
}
예제 #13
0
/* gfx_directx_unlock:
 *  Unlocks the surface.
 */
void gfx_directx_unlock(BITMAP *bmp)
{
   DDRAW_SURFACE *surf;
   BITMAP *parent;
   HRESULT hr;

   if (bmp->id & BMP_ID_SUB) {
      /* recurse when unlocking sub-bitmaps */
      parent = (BITMAP *)bmp->extra;
      gfx_directx_unlock(parent);
      if (!(parent->id & BMP_ID_LOCKED))
         bmp->id &= ~BMP_ID_LOCKED;
   }
   else {
      /* regular bitmaps can be unlocked directly */
      surf = DDRAW_SURFACE_OF(bmp);

      if (surf->lock_nesting > 0) {
         surf->lock_nesting--;

         if ((!surf->lock_nesting) && (bmp->id & BMP_ID_LOCKED)) {
            if (!(surf->flags & DDRAW_SURFACE_LOST)) {
               /* only unlock if it doesn't use pseudo video memory */
               hr = IDirectDrawSurface2_Unlock(surf->id, NULL);

               /* If the surface has been lost, try to restore all surfaces
                * and, on success, try again to unlock the surface.
                */
               if (hr == DDERR_SURFACELOST) {
                  if (restore_all_ddraw_surfaces() == 0)
                     hr = IDirectDrawSurface2_Unlock(surf->id, NULL);
               }

               if (FAILED(hr))
                  _TRACE(PREFIX_E "Can't unlock surface (%x)\n", hr);
            }

            bmp->id &= ~BMP_ID_LOCKED;
         }

         /* release bitmap for other threads */
         _exit_gfx_critical();
      }
   }
}
예제 #14
0
파일: wddbmpl.c 프로젝트: 4144/aseprite
/* unregister_all_ddraw_surfaces:
 *  Removes all surfaces from the linked list.
 */
void unregister_all_ddraw_surfaces(void)
{
   DDRAW_SURFACE *item, *next_item;

   _enter_gfx_critical();

   next_item = ddraw_surface_list;

   while (next_item) {
      item = next_item;
      next_item = next_item->next;
      item->next = NULL;
      item->prev = NULL;
   }

   ddraw_surface_list = NULL;

   _exit_gfx_critical();
}
예제 #15
0
/* ddraw_blit_to_self:
 *  Accelerated vram -> vram blitting routine.
 */
static void ddraw_blit_to_self(BITMAP * source, BITMAP * dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
{
   RECT src_rect;
   int dest_parent_x = dest_x + dest->x_ofs;
   int dest_parent_y = dest_y + dest->y_ofs;
   BITMAP *dest_parent;
   BITMAP *source_parent;

   src_rect.left = source_x + source->x_ofs;
   src_rect.top = source_y + source->y_ofs;
   src_rect.right = source_x + source->x_ofs + width;
   src_rect.bottom = source_y + source->y_ofs + height;

   /* find parents */
   dest_parent = dest;
   while (dest_parent->id & BMP_ID_SUB)
      dest_parent = (BITMAP *)dest_parent->extra;

   source_parent = source;
   while (source_parent->id & BMP_ID_SUB)
      source_parent = (BITMAP *)source_parent->extra;
   
   _enter_gfx_critical();
   gfx_directx_release_lock(dest);
   gfx_directx_release_lock(source);
   
   IDirectDrawSurface2_BltFast(DDRAW_SURFACE_OF(dest_parent)->id, dest_parent_x, dest_parent_y,
                               DDRAW_SURFACE_OF(source_parent)->id, &src_rect,
                               DDBLTFAST_WAIT);
   _exit_gfx_critical();
   
   /* only for windowed mode */
   if ((gfx_driver->id == GFX_DIRECTX_WIN) && (dest_parent == gfx_directx_forefront_bitmap)) {
      src_rect.left   = dest_parent_x;
      src_rect.top    = dest_parent_y;
      src_rect.right  = dest_parent_x + width;
      src_rect.bottom = dest_parent_y + height;
      win_gfx_driver->paint(&src_rect);
   }
}
예제 #16
0
/* ddraw_clear_to_color:
 *  Accelerated screen clear routine.
 */
static void ddraw_clear_to_color(BITMAP * bitmap, int color)
{
   RECT dest_rect;
   HRESULT hr;
   DDBLTFX blt_fx;
   BITMAP *parent;

   dest_rect.left = bitmap->cl + bitmap->x_ofs;
   dest_rect.top = bitmap->ct + bitmap->y_ofs;
   dest_rect.right = bitmap->x_ofs + bitmap->cr;
   dest_rect.bottom = bitmap->y_ofs + bitmap->cb;

   /* find parent */
   parent = bitmap;
   while (parent->id & BMP_ID_SUB)
      parent = (BITMAP *)parent->extra;

   /* set fill color */
   blt_fx.dwSize = sizeof(blt_fx);
   blt_fx.dwDDFX = 0;
   blt_fx.dwFillColor = color;

   _enter_gfx_critical();
   gfx_directx_release_lock(bitmap);

   hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(parent)->id, &dest_rect,
                                NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blt_fx);
   _exit_gfx_critical();

   if (FAILED(hr))
      _TRACE(PREFIX_E "Blt failed (%x)\n", hr);

   /* only for windowed mode */
   if ((gfx_driver->id == GFX_DIRECTX_WIN) && (parent == gfx_directx_forefront_bitmap))
      win_gfx_driver->paint(&dest_rect);
}
예제 #17
0
/* ddraw_vline:
 *  Accelerated vline routine.
 */
static void ddraw_vline(BITMAP *bitmap, int x, int y1, int y2, int color)
{
   RECT dest_rect;
   HRESULT hr;
   DDBLTFX blt_fx;
   BITMAP *parent;

   if (_drawing_mode != DRAW_MODE_SOLID) {
      _orig_vline(bitmap, x, y1, y2, color);
      return;
   }

   if (y1 > y2) {
      int tmp = y1;
      y1 = y2;
      y2 = tmp;
   }

   if (bitmap->clip) {
      if ((x < bitmap->cl) || (x >= bitmap->cr))
	 return;

      if (y1 < bitmap->ct)
	 y1 = bitmap->ct;

      if (y2 >= bitmap->cb)
	 y2 = bitmap->cb-1;

      if (y2 < y1)
	 return;
   }

   dest_rect.top = y1 + bitmap->y_ofs;
   dest_rect.left = x + bitmap->x_ofs;
   dest_rect.bottom = y2 + bitmap->y_ofs + 1;
   dest_rect.right = x + bitmap->x_ofs + 1;

   /* find parent */
   parent = bitmap;
   while (parent->id & BMP_ID_SUB)
      parent = (BITMAP *)parent->extra;

   /* set fill color */
   blt_fx.dwSize = sizeof(blt_fx);
   blt_fx.dwDDFX = 0;
   blt_fx.dwFillColor = color;

   _enter_gfx_critical();
   gfx_directx_release_lock(bitmap);

   hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(parent)->id, &dest_rect,
                                NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blt_fx);
   _exit_gfx_critical();

   if (FAILED(hr))
      _TRACE(PREFIX_E "Blt failed (%x)\n", hr);

   /* only for windowed mode */
   if ((gfx_driver->id == GFX_DIRECTX_WIN) && (parent == gfx_directx_forefront_bitmap))
      win_gfx_driver->paint(&dest_rect);
}
예제 #18
0
/* render_proc:
 *  Timer proc that updates the window.
 */
static void render_proc(void)
{
   int top_line, bottom_line;
   HDC hdc = NULL;
   HWND allegro_wnd = win_get_window();

   /* to prevent reentrant calls */
   if (render_semaphore)
      return;

   render_semaphore = TRUE;

   /* to prevent the drawing threads and the rendering proc
    * from concurrently accessing the dirty lines array.
    */
   _enter_gfx_critical();

   if (!gdi_screen) {
      _exit_gfx_critical();
      render_semaphore = FALSE;
      return;
   }

   /* pseudo dirty rectangles mechanism:
    *  at most only one GDI call is performed for each frame,
    *  a true dirty rectangles mechanism makes the demo game
    *  unplayable in 640x480 on my system.
    */

   /* find the first dirty line */
   top_line = 0;

   while (!gdi_dirty_lines[top_line])
      top_line++;

   if (top_line < gfx_gdi.h) {
      /* find the last dirty line */
      bottom_line = gfx_gdi.h-1;

      while (!gdi_dirty_lines[bottom_line])
         bottom_line--;

      hdc = GetDC(allegro_wnd);

      if (_color_depth == 8)
         set_palette_to_hdc(hdc, palette);

      blit_to_hdc(gdi_screen, hdc, 0, top_line, 0, top_line,
                  gfx_gdi.w, bottom_line - top_line + 1);

      /* update mouse pointer if needed */
      if (mouse_on) {
         if ((mouse_ypos+wgdi_mouse_sprite->h > top_line) && (mouse_ypos <= bottom_line)) {
            blit(gdi_screen, mouse_backbuffer, mouse_xpos, mouse_ypos, 0, 0,
                 mouse_backbuffer->w, mouse_backbuffer->h);

            update_mouse_pointer(mouse_xpos, mouse_ypos, TRUE);
         }
      }
      
      /* clean up the dirty lines */
      while (top_line <= bottom_line)
         gdi_dirty_lines[top_line++] = 0;

      ReleaseDC(allegro_wnd, hdc);
   }

   _exit_gfx_critical();

   /* simulate vertical retrace */
   PulseEvent(vsync_event);

   render_semaphore = FALSE;
}