Ejemplo n.º 1
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);
   }
}
Ejemplo n.º 2
0
/* win_get_dc: (WinAPI)
 *  Returns device context of a video or system bitmap.
 */
HDC win_get_dc(BITMAP *bmp)
{
   LPDIRECTDRAWSURFACE2 ddsurf;
   HDC dc;
   HRESULT hr;

   if (bmp) {
      if (bmp->id & (BMP_ID_SYSTEM | BMP_ID_VIDEO)) {
         ddsurf = DDRAW_SURFACE_OF(bmp)->id;
         hr = IDirectDrawSurface2_GetDC(ddsurf, &dc);

         /* If the surface has been lost, try to restore all surfaces
          * and, on success, try again to get the DC.
          */
         if (hr == DDERR_SURFACELOST) {
            if (restore_all_ddraw_surfaces() == 0)
               hr = IDirectDrawSurface2_GetDC(ddsurf, &dc);
         }

         if (hr == DD_OK)
            return dc;
      }
   }

   return NULL;
}
Ejemplo n.º 3
0
/* gfx_directx_destroy_system_bitmap:
 */
void gfx_directx_destroy_system_bitmap(BITMAP *bmp)
{
   /* Special case: use normal destroy_bitmap() for subbitmaps of system
    * bitmaps. Checked here rather than in destroy_bitmap() because that
    * function should not make assumptions about the relation between system
    * bitmaps and subbitmaps thereof. This duplicates code though and a
    * different solution would be better.
    */
   if (is_sub_bitmap(bmp)) {
      if (system_driver->destroy_bitmap) {
        if (system_driver->destroy_bitmap(bmp))
           return;
      }

      if (bmp->dat)
        _AL_FREE(bmp->dat);

      _AL_FREE(bmp);

      return;
   }

   /* destroy the surface */
   gfx_directx_destroy_surface(DDRAW_SURFACE_OF(bmp));

   _AL_FREE(bmp);
}
Ejemplo n.º 4
0
/* gfx_directx_destroy_video_bitmap:
 */
void gfx_directx_destroy_video_bitmap(BITMAP *bmp)
{
   DDRAW_SURFACE *surf, *tail_page;

   surf = DDRAW_SURFACE_OF(bmp);

   if ((surf == flipping_page[0]) || (surf == flipping_page[1]) || (surf == flipping_page[2])) {
      /* handle surfaces belonging to the flipping chain */
      if (--n_flipping_pages > 0) {
         tail_page = flipping_page[n_flipping_pages];

         /* If the surface attached to the bitmap is not the tail page
          * that is to be destroyed, attach it to the bitmap whose
          * attached surface is the tail page.
          */
         if (surf != tail_page) {
            surf->parent_bmp = tail_page->parent_bmp;
            surf->parent_bmp->extra = surf;
         }

         /* remove the tail page from the flipping chain */
         recreate_flipping_chain(n_flipping_pages);
         _AL_FREE(tail_page);
      }
      flipping_page[n_flipping_pages] = NULL;
   }
   else {
      /* destroy the surface */
      gfx_directx_destroy_surface(surf);
   }

   _AL_FREE(bmp);
}
Ejemplo n.º 5
0
/* gfx_directx_enable_triple_buffering:
 *  Checks graphic driver for triple buffering capability.
 */
void gfx_directx_enable_triple_buffering(GFX_DRIVER *drv)
{
   HRESULT hr;

   hr = IDirectDrawSurface2_GetFlipStatus(DDRAW_SURFACE_OF(gfx_directx_forefront_bitmap)->id, DDGFS_ISFLIPDONE);
   if ((hr == DD_OK) || (hr == DDERR_WASSTILLDRAWING)) {
      drv->poll_scroll = gfx_directx_poll_scroll;
      gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER;
   }
}
Ejemplo n.º 6
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);
   }
}
Ejemplo n.º 7
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;
      }
   }
}
Ejemplo n.º 8
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();
      }
   }
}
Ejemplo n.º 9
0
/* flip_with_forefront_bitmap:
 *  Worker function for DirectDraw page flipping.
 */
static int flip_with_forefront_bitmap(BITMAP *bmp, int wait)
{
   DDRAW_SURFACE *surf;
   HRESULT hr;

   /* flip only in the foreground */
   if (!_win_app_foreground) {
      _win_thread_switch_out();
      return 0;
   }

   /* retrieve the underlying surface */
   surf = DDRAW_SURFACE_OF(bmp);
   if (surf == flipping_page[0])
      return 0;

   ASSERT((surf == flipping_page[1]) || (surf == flipping_page[2]));

   /* flip the contents of the surfaces */
   hr = IDirectDrawSurface2_Flip(flipping_page[0]->id, surf->id, wait ? DDFLIP_WAIT : 0);

   /* if the surface has been lost, try to restore all surfaces */
   if (hr == DDERR_SURFACELOST) {
      if (restore_all_ddraw_surfaces() == 0)
         hr = IDirectDrawSurface2_Flip(flipping_page[0]->id, surf->id, wait ? DDFLIP_WAIT : 0);
   }

   if (FAILED(hr)) {
      _TRACE(PREFIX_E "Can't flip (%s)\n", dd_err(hr));
      return -1;
   }

   /* attach the surface to the former forefront bitmap */
   surf->parent_bmp = flipping_page[0]->parent_bmp;
   surf->parent_bmp->extra = surf;

   /* make the bitmap point to the forefront surface */
   flipping_page[0]->parent_bmp = bmp;
   bmp->extra = flipping_page[0];

   return 0;
}
Ejemplo n.º 10
0
/* win_release_dc: (WinAPI)
 *  Releases device context of a video or system bitmap.
 */
void win_release_dc(BITMAP *bmp, HDC dc)
{
   LPDIRECTDRAWSURFACE2 ddsurf;
   HRESULT hr;

   if (bmp) {
      if (bmp->id & (BMP_ID_SYSTEM | BMP_ID_VIDEO)) {
         ddsurf = DDRAW_SURFACE_OF(bmp)->id;
         hr = IDirectDrawSurface2_ReleaseDC(ddsurf, dc);

         /* If the surface has been lost, try to restore all surfaces
          * and, on success, try again to release the DC.
          */
         if (hr == DDERR_SURFACELOST) {
            if (restore_all_ddraw_surfaces() == 0)
               hr = IDirectDrawSurface2_ReleaseDC(ddsurf, dc);
         }
      }
   }
}
Ejemplo n.º 11
0
/* gfx_directx_release_lock:
 *  Releases the surface lock, for hardware accelerated drawing.
 */
void gfx_directx_release_lock(BITMAP *bmp)
{
   DDRAW_SURFACE *surf;
   HRESULT hr;

   /* handle display switch */
   if (!_win_app_foreground)
      gfx_directx_switch_out();

   /* find parent */
   while (bmp->id & BMP_ID_SUB) {
      bmp->id &= ~BMP_ID_LOCKED;
      bmp = (BITMAP *)bmp->extra;
   }

   if (bmp->id & BMP_ID_LOCKED) {
      surf = DDRAW_SURFACE_OF(bmp);

      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 release lock (%x)\n", hr);
      }

      bmp->id &= ~BMP_ID_LOCKED;
   }
}
Ejemplo n.º 12
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);
}
Ejemplo n.º 13
0
/* gfx_directx_lock:
 *  Locks the surface and prepares the lines array of the bitmap.
 */
void gfx_directx_lock(BITMAP *bmp)
{
   DDRAW_SURFACE *surf;
   BITMAP *parent;
   HRESULT hr;
   DDSURFACEDESC ddsurf_desc;
   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_lock(parent);
      bmp->id |= BMP_ID_LOCKED;

      /* 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 {
      /* require exclusive ownership of the bitmap */
      _enter_gfx_critical();

      /* handle display switch */
      if (!_win_app_foreground)
         gfx_directx_switch_out();

      /* this is a real bitmap, so can be locked directly */
      surf = DDRAW_SURFACE_OF(bmp);
      surf->lock_nesting++;

      if (!(bmp->id & BMP_ID_LOCKED)) {
         /* try to lock surface */
         bmp->id |= BMP_ID_LOCKED;
         surf->flags &= ~DDRAW_SURFACE_LOST;

         ddsurf_desc.dwSize = sizeof(DDSURFACEDESC);
         ddsurf_desc.dwFlags = 0;

         hr = IDirectDrawSurface2_Lock(surf->id, NULL, &ddsurf_desc,
                                    DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);

         /* If the surface has been lost, try to restore all surfaces
          * and, on success, try again to lock the surface.
          */
         if (hr == DDERR_SURFACELOST) {
            if (restore_all_ddraw_surfaces() == 0) {
               ddsurf_desc.dwSize = sizeof(DDSURFACEDESC);
               ddsurf_desc.dwFlags = 0;

               hr = IDirectDrawSurface2_Lock(surf->id, NULL, &ddsurf_desc,
                                          DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);
            }
         }

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

            /* lock failed, use pseudo surface memory */
            surf->flags |= DDRAW_SURFACE_LOST;
            data = pseudo_surf_mem;
            pitch = 0;
         }
         else {
            data = ddsurf_desc.lpSurface;
            pitch = ddsurf_desc.lPitch;
         }

         /* prepare line array */
         if (data != bmp->line[0]) {
            for (y = 0; y < bmp->h; y++) {
               bmp->line[y] = data;
               data += pitch;
            }
         }
      }
   }
}
Ejemplo n.º 14
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);
}
Ejemplo n.º 15
0
/* gfx_directx_create_video_bitmap:
 */
BITMAP *gfx_directx_create_video_bitmap(int width, int height)
{
   DDRAW_SURFACE *surf;
   BITMAP *bmp;

   /* try to detect page flipping and triple buffering patterns */
   if ((width == gfx_directx_forefront_bitmap->w) && (height == gfx_directx_forefront_bitmap->h)) {

      switch (n_flipping_pages) {

         case 0:
            /* recycle the forefront surface as the first flipping page */
            flipping_page[0] = DDRAW_SURFACE_OF(gfx_directx_forefront_bitmap);
            bmp = gfx_directx_make_bitmap_from_surface(flipping_page[0], width, height, BMP_ID_VIDEO);
            if (bmp) {
               flipping_page[0]->parent_bmp = bmp;
               n_flipping_pages++;
               return bmp;
            }
            else {
               flipping_page[0] = NULL;
               return NULL;
            }

         case 1:
         case 2:
            /* try to attach an additional page to the flipping chain */
            flipping_page[n_flipping_pages] = _AL_MALLOC(sizeof(DDRAW_SURFACE));
            if (recreate_flipping_chain(n_flipping_pages+1) == 0) {
               bmp = gfx_directx_make_bitmap_from_surface(flipping_page[n_flipping_pages], width, height, BMP_ID_VIDEO);
               if (bmp) {
                  flipping_page[n_flipping_pages]->parent_bmp = bmp;
                  n_flipping_pages++;
                  return bmp;
               }
            }

            recreate_flipping_chain(n_flipping_pages);
            _AL_FREE(flipping_page[n_flipping_pages]);
            flipping_page[n_flipping_pages] = NULL;
            return NULL;
      }
   }

   /* create the DirectDraw surface */
   if (ddpixel_format)
      surf = gfx_directx_create_surface(width, height, ddpixel_format, DDRAW_SURFACE_SYSTEM);
   else
      surf = gfx_directx_create_surface(width, height, NULL, DDRAW_SURFACE_VIDEO);

   if (!surf)
      return NULL;

   /* create the bitmap that wraps up the surface */
   bmp = gfx_directx_make_bitmap_from_surface(surf, width, height, BMP_ID_VIDEO);
   if (!bmp) {
      gfx_directx_destroy_surface(surf);
      return NULL;
   }

   return bmp;
}