/* DirectDrawSurface HAL driver * * Copyright 2001 TransGaming Technologies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include #define NONAMELESSUNION #define NONAMELESSSTRUCT #include "wine/debug.h" #include "ddraw_private.h" #include "ddraw/user.h" #include "ddraw/hal.h" #include "dsurface/main.h" #include "dsurface/dib.h" #include "dsurface/user.h" #include "dsurface/hal.h" WINE_DEFAULT_DEBUG_CHANNEL(ddraw); static IDirectDrawSurface7Vtbl HAL_IDirectDrawSurface7_VTable; static HRESULT HAL_DirectDrawSurface_create_surface(IDirectDrawSurfaceImpl* This, IDirectDrawImpl* pDD) { HAL_PRIV_VAR(priv, This); HAL_DDRAW_PRIV_VAR(ddpriv, pDD); LPDDRAWI_DIRECTDRAW_GBL dd_gbl = pDD->local.lpGbl; LPDDRAWI_DDRAWSURFACE_LCL local = &This->local; DDHAL_CREATESURFACEDATA data; HRESULT hr; data.lpDD = dd_gbl; data.lpDDSurfaceDesc = (LPDDSURFACEDESC)&This->surface_desc; data.lplpSList = &local; data.dwSCnt = 1; data.ddRVal = 0; data.CreateSurface = dd_gbl->lpDDCBtmp->HALDD.CreateSurface; hr = data.CreateSurface(&data); if (hr == DDHAL_DRIVER_HANDLED) { if (This->global.fpVidMem < 4) { /* grab framebuffer data from current_mode */ priv->hal.fb_pitch = dd_gbl->vmiData.lDisplayPitch; priv->hal.fb_vofs = ddpriv->hal.next_vofs; priv->hal.fb_addr = ((LPBYTE)dd_gbl->vmiData.fpPrimary) + dd_gbl->vmiData.lDisplayPitch * priv->hal.fb_vofs; TRACE("vofs=%ld, addr=%p\n", priv->hal.fb_vofs, priv->hal.fb_addr); ddpriv->hal.next_vofs += This->surface_desc.dwHeight; This->global.fpVidMem = (FLATPTR)priv->hal.fb_addr; This->global.u4.lPitch = priv->hal.fb_pitch; } This->surface_desc.lpSurface = (LPVOID)This->global.fpVidMem; This->surface_desc.dwFlags |= DDSD_LPSURFACE; if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) { This->surface_desc.u1.dwLinearSize = This->global.u4.dwLinearSize; This->surface_desc.dwFlags |= DDSD_LINEARSIZE; } else { This->surface_desc.u1.lPitch = This->global.u4.lPitch; This->surface_desc.dwFlags |= DDSD_PITCH; } } else priv->hal.need_late = TRUE; return data.ddRVal; } static inline BOOL HAL_IsUser(IDirectDrawSurfaceImpl* This) { HAL_PRIV_VAR(priv, This); if (This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_EXECUTEBUFFER)) return FALSE; if (priv->hal.fb_addr) return FALSE; return TRUE; } HRESULT HAL_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This, IDirectDrawImpl* pDD, const DDSURFACEDESC2* pDDSD) { HAL_PRIV_VAR(priv, This); LPDDRAWI_DIRECTDRAW_GBL dd_gbl = pDD->local.lpGbl; HRESULT hr; TRACE("(%p,%p,%p)\n",This,pDD,pDDSD); /* copy surface_desc, we may want to modify it before DIB construction */ This->surface_desc = *pDDSD; /* the driver may want to dereference these pointers */ This->local.lpSurfMore = &This->more; This->local.lpGbl = &This->global; This->gmore = &This->global_more; if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) { hr = HAL_DirectDrawSurface_create_surface(This, pDD); if (FAILED(hr)) return hr; hr = DIB_DirectDrawSurface_Construct(This, pDD, &This->surface_desc); if (FAILED(hr)) return hr; } else if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) { FIXME("create execute buffer\n"); return DDERR_GENERIC; } else { if (!(dd_gbl->dwFlags & DDRAWI_MODECHANGED)) { /* force a mode set (HALs like DGA may need it) */ hr = HAL_DirectDraw_SetDisplayMode(ICOM_INTERFACE(pDD, IDirectDraw7), pDD->width, pDD->height, pDD->pixelformat.u1.dwRGBBitCount, 0, 0); if (FAILED(hr)) return hr; } if (dd_gbl->vmiData.fpPrimary) { hr = HAL_DirectDrawSurface_create_surface(This, pDD); if (FAILED(hr)) return hr; if (priv->hal.need_late) { /* this doesn't make sense... driver error? */ ERR("driver failed to create framebuffer surface\n"); return DDERR_GENERIC; } hr = DIB_DirectDrawSurface_Construct(This, pDD, &This->surface_desc); if (FAILED(hr)) return hr; } else { /* no framebuffer, construct User-based primary */ hr = User_DirectDrawSurface_Construct(This, pDD, pDDSD); if (FAILED(hr)) return hr; /* must notify HAL *after* creating User-based primary */ /* (or use CreateSurfaceEx, which we don't yet) */ hr = HAL_DirectDrawSurface_create_surface(This, pDD); if (FAILED(hr)) return hr; priv->hal.need_late = FALSE; } } ICOM_INIT_INTERFACE(This, IDirectDrawSurface7, HAL_IDirectDrawSurface7_VTable); This->final_release = HAL_DirectDrawSurface_final_release; This->late_allocate = HAL_DirectDrawSurface_late_allocate; This->duplicate_surface = HAL_DirectDrawSurface_duplicate_surface; This->flip_data = HAL_DirectDrawSurface_flip_data; This->flip_update = HAL_DirectDrawSurface_flip_update; This->set_palette = HAL_DirectDrawSurface_set_palette; This->get_display_window = HAL_DirectDrawSurface_get_display_window; return DD_OK; } HRESULT HAL_DirectDrawSurface_Create(IDirectDrawImpl *pDD, const DDSURFACEDESC2 *pDDSD, LPDIRECTDRAWSURFACE7 *ppSurf, IUnknown *pUnkOuter) { IDirectDrawSurfaceImpl* This; HRESULT hr; assert(pUnkOuter == NULL); This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This) + sizeof(HAL_DirectDrawSurfaceImpl)); if (This == NULL) return E_OUTOFMEMORY; This->private = (HAL_DirectDrawSurfaceImpl*)(This+1); hr = HAL_DirectDrawSurface_Construct(This, pDD, pDDSD); if (FAILED(hr)) HeapFree(GetProcessHeap(), 0, This); else *ppSurf = ICOM_INTERFACE(This, IDirectDrawSurface7); return hr; } void HAL_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This) { LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->more.lpDD_lcl->lpGbl; DDHAL_DESTROYSURFACEDATA data; /* destroy HAL surface */ data.lpDD = dd_gbl; data.lpDDSurface = &This->local; data.ddRVal = 0; data.DestroySurface = dd_gbl->lpDDCBtmp->HALDDSurface.DestroySurface; data.DestroySurface(&data); if (HAL_IsUser(This)) { User_DirectDrawSurface_final_release(This); } else { DIB_DirectDrawSurface_final_release(This); } } HRESULT HAL_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This) { HAL_PRIV_VAR(priv, This); if (priv->hal.need_late) { priv->hal.need_late = FALSE; return HAL_DirectDrawSurface_create_surface(This, This->ddraw_owner); } return DD_OK; } void HAL_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* pal) { LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->more.lpDD_lcl->lpGbl; DDHAL_SETPALETTEDATA data; DIB_DirectDrawSurface_set_palette(This, pal); data.lpDD = dd_gbl; data.lpDDSurface = &This->local; data.lpDDPalette = (pal != NULL ? &pal->global : NULL); data.ddRVal = 0; data.Attach = TRUE; /* what's this? */ data.SetPalette = dd_gbl->lpDDCBtmp->HALDDSurface.SetPalette; if (data.SetPalette) data.SetPalette(&data); } HRESULT HAL_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This, LPDIRECTDRAWSURFACE7* ppDup) { return HAL_DirectDrawSurface_Create(This->ddraw_owner, &This->surface_desc, ppDup, NULL); } void HAL_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags) { LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->more.lpDD_lcl->lpGbl; DDHAL_LOCKDATA data; data.lpDD = dd_gbl; data.lpDDSurface = &This->local; data.ddRVal = 0; data.lpSurfData = This->surface_desc.lpSurface; /* FIXME: correct? */ if (pRect) { data.rArea.top = pRect->top; data.rArea.bottom = pRect->bottom; data.rArea.left = pRect->left; data.rArea.right = pRect->right; data.bHasRect = TRUE; } else { data.bHasRect = FALSE; } data.dwFlags = dwFlags; data.Lock = dd_gbl->lpDDCBtmp->HALDDSurface.Lock; if (data.Lock && (data.Lock(&data) == DDHAL_DRIVER_HANDLED)) return; if (HAL_IsUser(This)) { User_DirectDrawSurface_lock_update(This, pRect, dwFlags); } else { Main_DirectDrawSurface_lock_update(This, pRect, dwFlags); } } void HAL_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect) { LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->more.lpDD_lcl->lpGbl; DDHAL_UNLOCKDATA data; data.lpDD = dd_gbl; data.lpDDSurface = &This->local; data.ddRVal = 0; data.Unlock = dd_gbl->lpDDCBtmp->HALDDSurface.Unlock; if (data.Unlock && (data.Unlock(&data) == DDHAL_DRIVER_HANDLED)) return; if (HAL_IsUser(This)) { User_DirectDrawSurface_unlock_update(This, pRect); } else { Main_DirectDrawSurface_unlock_update(This, pRect); } } BOOL HAL_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front, IDirectDrawSurfaceImpl* back, DWORD dwFlags) { HAL_PRIV_VAR(front_priv, front); HAL_PRIV_VAR(back_priv, back); LPDDRAWI_DIRECTDRAW_GBL dd_gbl = front->more.lpDD_lcl->lpGbl; DDHAL_FLIPDATA data; BOOL ret; { DWORD tmp; tmp = front_priv->hal.fb_vofs; front_priv->hal.fb_vofs = back_priv->hal.fb_vofs; back_priv->hal.fb_vofs = tmp; } { LPVOID tmp; tmp = front_priv->hal.fb_addr; front_priv->hal.fb_addr = back_priv->hal.fb_addr; back_priv->hal.fb_addr = tmp; } if (HAL_IsUser(front)) { ret = User_DirectDrawSurface_flip_data(front, back, dwFlags); } else { ret = DIB_DirectDrawSurface_flip_data(front, back, dwFlags); } TRACE("(%p,%p)\n",front,back); data.lpDD = dd_gbl; data.lpSurfCurr = &front->local; data.lpSurfTarg = &back->local; data.lpSurfCurrLeft = NULL; data.lpSurfTargLeft = NULL; data.dwFlags = dwFlags; data.ddRVal = 0; data.Flip = dd_gbl->lpDDCBtmp->HALDDSurface.Flip; if (data.Flip) if (data.Flip(&data) == DDHAL_DRIVER_HANDLED) ret = FALSE; return ret; } void HAL_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This, DWORD dwFlags) { if (HAL_IsUser(This)) { User_DirectDrawSurface_flip_update(This, dwFlags); } } HWND HAL_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This) { return 0; } static IDirectDrawSurface7Vtbl HAL_IDirectDrawSurface7_VTable = { Main_DirectDrawSurface_QueryInterface, Main_DirectDrawSurface_AddRef, Main_DirectDrawSurface_Release, Main_DirectDrawSurface_AddAttachedSurface, Main_DirectDrawSurface_AddOverlayDirtyRect, DIB_DirectDrawSurface_Blt, Main_DirectDrawSurface_BltBatch, DIB_DirectDrawSurface_BltFast, Main_DirectDrawSurface_DeleteAttachedSurface, Main_DirectDrawSurface_EnumAttachedSurfaces, Main_DirectDrawSurface_EnumOverlayZOrders, Main_DirectDrawSurface_Flip, Main_DirectDrawSurface_GetAttachedSurface, Main_DirectDrawSurface_GetBltStatus, Main_DirectDrawSurface_GetCaps, Main_DirectDrawSurface_GetClipper, Main_DirectDrawSurface_GetColorKey, Main_DirectDrawSurface_GetDC, Main_DirectDrawSurface_GetFlipStatus, Main_DirectDrawSurface_GetOverlayPosition, Main_DirectDrawSurface_GetPalette, Main_DirectDrawSurface_GetPixelFormat, Main_DirectDrawSurface_GetSurfaceDesc, Main_DirectDrawSurface_Initialize, Main_DirectDrawSurface_IsLost, Main_DirectDrawSurface_Lock, Main_DirectDrawSurface_ReleaseDC, DIB_DirectDrawSurface_Restore, Main_DirectDrawSurface_SetClipper, Main_DirectDrawSurface_SetColorKey, Main_DirectDrawSurface_SetOverlayPosition, Main_DirectDrawSurface_SetPalette, Main_DirectDrawSurface_Unlock, Main_DirectDrawSurface_UpdateOverlay, Main_DirectDrawSurface_UpdateOverlayDisplay, Main_DirectDrawSurface_UpdateOverlayZOrder, Main_DirectDrawSurface_GetDDInterface, Main_DirectDrawSurface_PageLock, Main_DirectDrawSurface_PageUnlock, DIB_DirectDrawSurface_SetSurfaceDesc, Main_DirectDrawSurface_SetPrivateData, Main_DirectDrawSurface_GetPrivateData, Main_DirectDrawSurface_FreePrivateData, Main_DirectDrawSurface_GetUniquenessValue, Main_DirectDrawSurface_ChangeUniquenessValue, Main_DirectDrawSurface_SetPriority, Main_DirectDrawSurface_GetPriority, Main_DirectDrawSurface_SetLOD, Main_DirectDrawSurface_GetLOD };