|  | /*	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 <assert.h> | 
|  | #include <stdlib.h> | 
|  |  | 
|  | #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 | 
|  | }; |