Implemented DirectDraw's Hardware Abstraction Layer (HAL) interface.
[wine] / dlls / ddraw / dsurface / hal.c
1 /*      DirectDrawSurface HAL driver
2  *
3  * Copyright 2001 TransGaming Technologies Inc.
4  */
5
6 #include "config.h"
7
8 #include <assert.h>
9 #include <stdlib.h>
10
11 #include "debugtools.h"
12 #include "ddraw_private.h"
13 #include "ddraw/user.h"
14 #include "ddraw/hal.h"
15 #include "dsurface/main.h"
16 #include "dsurface/dib.h"
17 #include "dsurface/user.h"
18 #include "dsurface/hal.h"
19
20 DEFAULT_DEBUG_CHANNEL(ddraw);
21
22 static ICOM_VTABLE(IDirectDrawSurface7) HAL_IDirectDrawSurface7_VTable;
23
24 static HRESULT HAL_DirectDrawSurface_create_surface(IDirectDrawSurfaceImpl* This,
25                                                     IDirectDrawImpl* pDD)
26 {
27     HAL_PRIV_VAR(priv, This);
28     HAL_DDRAW_PRIV_VAR(ddpriv, pDD);
29     LPDDRAWI_DIRECTDRAW_GBL dd_gbl = pDD->local.lpGbl;
30     LPDDRAWI_DDRAWSURFACE_LCL local = &This->local;
31     DDHAL_CREATESURFACEDATA data;
32     HRESULT hr;
33
34     data.lpDD = dd_gbl;
35     data.lpDDSurfaceDesc = (LPDDSURFACEDESC)&This->surface_desc;
36     data.lplpSList = &local;
37     data.dwSCnt = 1;
38     data.ddRVal = 0;
39     data.CreateSurface = dd_gbl->lpDDCBtmp->HALDD.CreateSurface;
40     hr = data.CreateSurface(&data);
41
42     if (hr == DDHAL_DRIVER_HANDLED) {
43         if (This->global.fpVidMem < 4) {
44             /* grab framebuffer data from current_mode */
45             priv->hal.fb_pitch = dd_gbl->vmiData.lDisplayPitch;
46             priv->hal.fb_vofs  = ddpriv->hal.next_vofs;
47             priv->hal.fb_addr  = ((LPBYTE)dd_gbl->vmiData.fpPrimary) +
48                                  dd_gbl->vmiData.lDisplayPitch * priv->hal.fb_vofs;
49             TRACE("vofs=%ld, addr=%p\n", priv->hal.fb_vofs, priv->hal.fb_addr);
50             ddpriv->hal.next_vofs += This->surface_desc.dwHeight;
51
52             This->global.fpVidMem = (FLATPTR)priv->hal.fb_addr;
53         }
54         This->surface_desc.lpSurface = (LPVOID)This->global.fpVidMem;
55         This->surface_desc.dwFlags |= DDSD_LPSURFACE;
56         if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) {
57             This->surface_desc.u1.dwLinearSize = This->global.u4.dwLinearSize;
58             This->surface_desc.dwFlags |= DDSD_LINEARSIZE;
59         } else {
60             This->surface_desc.u1.lPitch = This->global.u4.lPitch;
61             This->surface_desc.dwFlags |= DDSD_PITCH;
62         }
63     }
64     else priv->hal.need_late = TRUE;
65
66     return data.ddRVal;
67 }
68
69 static inline BOOL HAL_IsUser(IDirectDrawSurfaceImpl* This)
70 {
71     HAL_PRIV_VAR(priv, This);
72     if (This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_TEXTURE | DDSCAPS_EXECUTEBUFFER))
73         return FALSE;
74     if (priv->hal.fb_addr)
75         return FALSE;
76     return TRUE;
77 }
78
79 HRESULT
80 HAL_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl* This,
81                                 IDirectDrawImpl* pDD,
82                                 const DDSURFACEDESC2* pDDSD)
83 {
84     HAL_PRIV_VAR(priv, This);
85     LPDDRAWI_DIRECTDRAW_GBL dd_gbl = pDD->local.lpGbl;
86     HRESULT hr;
87
88     TRACE("(%p,%p,%p)\n",This,pDD,pDDSD);
89
90     /* copy surface_desc, we may want to modify it before DIB construction */
91     This->surface_desc = *pDDSD;
92
93     /* the driver may want to dereference these pointers */
94     This->local.lpSurfMore = &This->more;
95     This->local.lpGbl = &This->global;   
96     This->gmore = &This->global_more;
97
98     if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
99         hr = HAL_DirectDrawSurface_create_surface(This, pDD);
100         if (FAILED(hr)) return hr;
101
102         hr = DIB_DirectDrawSurface_Construct(This, pDD, &This->surface_desc);
103         if (FAILED(hr)) return hr;
104     }
105     else if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER) {
106         FIXME("create execute buffer\n");
107         return DDERR_GENERIC;
108     }
109     else {
110         if (!(dd_gbl->dwFlags & DDRAWI_MODECHANGED)) {
111             /* force a mode set (HALs like DGA may need it) */
112             hr = HAL_DirectDraw_SetDisplayMode(ICOM_INTERFACE(pDD, IDirectDraw7),
113                                                pDD->width, pDD->height,
114                                                pDD->pixelformat.u1.dwRGBBitCount,
115                                                0, 0);
116             if (FAILED(hr)) return hr;
117         }
118
119         if (dd_gbl->vmiData.fpPrimary) {
120             hr = HAL_DirectDrawSurface_create_surface(This, pDD);
121             if (FAILED(hr)) return hr;
122
123             if (priv->hal.need_late) {
124                 /* this doesn't make sense... driver error? */
125                 ERR("driver failed to create framebuffer surface\n");
126                 return DDERR_GENERIC;
127             }
128
129             hr = DIB_DirectDrawSurface_Construct(This, pDD, &This->surface_desc);
130             if (FAILED(hr)) return hr;
131         } else {
132             /* no framebuffer, construct User-based primary */
133             hr = User_DirectDrawSurface_Construct(This, pDD, pDDSD);
134             if (FAILED(hr)) return hr;
135
136             /* must notify HAL *after* creating User-based primary */
137             /* (or use CreateSurfaceEx, which we don't yet) */
138             hr = HAL_DirectDrawSurface_create_surface(This, pDD);
139             if (FAILED(hr)) return hr;
140
141             priv->hal.need_late = FALSE;
142         }
143     }
144
145     ICOM_INIT_INTERFACE(This, IDirectDrawSurface7,
146                         HAL_IDirectDrawSurface7_VTable);
147
148     This->final_release = HAL_DirectDrawSurface_final_release;
149     This->late_allocate = HAL_DirectDrawSurface_late_allocate;
150     This->duplicate_surface = HAL_DirectDrawSurface_duplicate_surface;
151
152     This->flip_data   = HAL_DirectDrawSurface_flip_data;
153     This->flip_update = HAL_DirectDrawSurface_flip_update;
154
155     This->set_palette    = HAL_DirectDrawSurface_set_palette;
156
157     This->get_display_window = HAL_DirectDrawSurface_get_display_window;
158
159     return DD_OK;
160 }
161
162 HRESULT
163 HAL_DirectDrawSurface_Create(IDirectDrawImpl *pDD,
164                              const DDSURFACEDESC2 *pDDSD,
165                              LPDIRECTDRAWSURFACE7 *ppSurf,
166                              IUnknown *pUnkOuter)
167 {
168     IDirectDrawSurfaceImpl* This;
169     HRESULT hr;
170     assert(pUnkOuter == NULL);
171
172     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
173                      sizeof(*This) + sizeof(HAL_DirectDrawSurfaceImpl));
174     if (This == NULL) return E_OUTOFMEMORY;
175
176     This->private = (HAL_DirectDrawSurfaceImpl*)(This+1);
177
178     hr = HAL_DirectDrawSurface_Construct(This, pDD, pDDSD);
179     if (FAILED(hr))
180         HeapFree(GetProcessHeap(), 0, This);
181     else
182         *ppSurf = ICOM_INTERFACE(This, IDirectDrawSurface7);
183
184     return hr;
185 }
186
187 void HAL_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
188 {
189     LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->more.lpDD_lcl->lpGbl;
190     DDHAL_DESTROYSURFACEDATA data;
191
192     /* destroy HAL surface */
193     data.lpDD = dd_gbl;
194     data.lpDDSurface = &This->local;
195     data.ddRVal = 0;
196     data.DestroySurface = dd_gbl->lpDDCBtmp->HALDDSurface.DestroySurface;
197     data.DestroySurface(&data);
198
199     if (HAL_IsUser(This)) {
200         User_DirectDrawSurface_final_release(This);
201     } else {
202         DIB_DirectDrawSurface_final_release(This);
203     }
204 }
205
206 HRESULT HAL_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
207 {
208     HAL_PRIV_VAR(priv, This);
209     if (priv->hal.need_late) {
210         priv->hal.need_late = FALSE;
211         return HAL_DirectDrawSurface_create_surface(This, This->ddraw_owner);
212     }
213     return DD_OK;
214 }
215
216 void HAL_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
217                                        IDirectDrawPaletteImpl* pal) 
218 {
219     LPDDRAWI_DIRECTDRAW_GBL dd_gbl = This->more.lpDD_lcl->lpGbl;
220     DDHAL_SETPALETTEDATA data;
221
222     DIB_DirectDrawSurface_set_palette(This, pal);
223     data.lpDD = dd_gbl;
224     data.lpDDSurface = &This->local;
225     data.lpDDPalette = &pal->global;
226     data.ddRVal = 0;
227     data.Attach = TRUE; /* what's this? */
228     data.SetPalette = dd_gbl->lpDDCBtmp->HALDDSurface.SetPalette;
229     if (data.SetPalette)
230         data.SetPalette(&data);
231 }
232
233 HRESULT HAL_DirectDrawSurface_duplicate_surface(IDirectDrawSurfaceImpl* This,
234                                                 LPDIRECTDRAWSURFACE7* ppDup)
235 {
236     return HAL_DirectDrawSurface_Create(This->ddraw_owner,
237                                              &This->surface_desc, ppDup, NULL);
238 }
239
240 void HAL_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This,
241                                        LPCRECT pRect)
242 {
243     if (HAL_IsUser(This)) {
244         User_DirectDrawSurface_lock_update(This, pRect);
245     } else {
246         Main_DirectDrawSurface_lock_update(This, pRect);
247     }
248 }
249
250 void HAL_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
251                                          LPCRECT pRect)
252 {
253     if (HAL_IsUser(This)) {
254         User_DirectDrawSurface_unlock_update(This, pRect);
255     } else {
256         Main_DirectDrawSurface_unlock_update(This, pRect);
257     }
258 }
259
260 BOOL HAL_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
261                                      IDirectDrawSurfaceImpl* back,
262                                      DWORD dwFlags)
263 {
264     HAL_PRIV_VAR(front_priv, front);
265     HAL_PRIV_VAR(back_priv, back);
266     LPDDRAWI_DIRECTDRAW_GBL dd_gbl = front->more.lpDD_lcl->lpGbl;
267     DDHAL_FLIPDATA data;
268     BOOL ret;
269
270     {
271         DWORD tmp;
272         tmp = front_priv->hal.fb_vofs;
273         front_priv->hal.fb_vofs = back_priv->hal.fb_vofs;
274         back_priv->hal.fb_vofs = tmp;
275     }
276     {
277         LPVOID tmp;
278         tmp = front_priv->hal.fb_addr;
279         front_priv->hal.fb_addr = back_priv->hal.fb_addr;
280         back_priv->hal.fb_addr = tmp;
281     }
282
283     if (HAL_IsUser(front)) {
284         ret = User_DirectDrawSurface_flip_data(front, back, dwFlags);
285     } else {
286         ret = DIB_DirectDrawSurface_flip_data(front, back, dwFlags);
287     }
288
289     data.lpDD = dd_gbl;
290     data.lpSurfCurr = &front->local;
291     data.lpSurfTarg = &back->local;
292     data.lpSurfCurrLeft = NULL;
293     data.lpSurfTargLeft = NULL;
294     data.dwFlags = dwFlags;
295     data.ddRVal = 0;
296     data.Flip = dd_gbl->lpDDCBtmp->HALDDSurface.Flip;
297     if (data.Flip)
298         if (data.Flip(&data) == DDHAL_DRIVER_HANDLED) ret = FALSE;
299
300     return ret;
301 }
302
303 void HAL_DirectDrawSurface_flip_update(IDirectDrawSurfaceImpl* This, DWORD dwFlags)
304 {
305     if (HAL_IsUser(This)) {
306         User_DirectDrawSurface_flip_update(This, dwFlags);
307     }
308 }
309
310 HWND HAL_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
311 {
312     return 0;
313 }
314
315 static ICOM_VTABLE(IDirectDrawSurface7) HAL_IDirectDrawSurface7_VTable =
316 {
317     Main_DirectDrawSurface_QueryInterface,
318     Main_DirectDrawSurface_AddRef,
319     Main_DirectDrawSurface_Release,
320     Main_DirectDrawSurface_AddAttachedSurface,
321     Main_DirectDrawSurface_AddOverlayDirtyRect,
322     DIB_DirectDrawSurface_Blt,
323     Main_DirectDrawSurface_BltBatch,
324     DIB_DirectDrawSurface_BltFast,
325     Main_DirectDrawSurface_DeleteAttachedSurface,
326     Main_DirectDrawSurface_EnumAttachedSurfaces,
327     Main_DirectDrawSurface_EnumOverlayZOrders,
328     Main_DirectDrawSurface_Flip,
329     Main_DirectDrawSurface_GetAttachedSurface,
330     Main_DirectDrawSurface_GetBltStatus,
331     Main_DirectDrawSurface_GetCaps,
332     Main_DirectDrawSurface_GetClipper,
333     Main_DirectDrawSurface_GetColorKey,
334     Main_DirectDrawSurface_GetDC,
335     Main_DirectDrawSurface_GetFlipStatus,
336     Main_DirectDrawSurface_GetOverlayPosition,
337     Main_DirectDrawSurface_GetPalette,
338     Main_DirectDrawSurface_GetPixelFormat,
339     Main_DirectDrawSurface_GetSurfaceDesc,
340     Main_DirectDrawSurface_Initialize,
341     Main_DirectDrawSurface_IsLost,
342     Main_DirectDrawSurface_Lock,
343     Main_DirectDrawSurface_ReleaseDC,
344     DIB_DirectDrawSurface_Restore,
345     Main_DirectDrawSurface_SetClipper,
346     Main_DirectDrawSurface_SetColorKey,
347     Main_DirectDrawSurface_SetOverlayPosition,
348     Main_DirectDrawSurface_SetPalette,
349     Main_DirectDrawSurface_Unlock,
350     Main_DirectDrawSurface_UpdateOverlay,
351     Main_DirectDrawSurface_UpdateOverlayDisplay,
352     Main_DirectDrawSurface_UpdateOverlayZOrder,
353     Main_DirectDrawSurface_GetDDInterface,
354     Main_DirectDrawSurface_PageLock,
355     Main_DirectDrawSurface_PageUnlock,
356     DIB_DirectDrawSurface_SetSurfaceDesc,
357     Main_DirectDrawSurface_SetPrivateData,
358     Main_DirectDrawSurface_GetPrivateData,
359     Main_DirectDrawSurface_FreePrivateData,
360     Main_DirectDrawSurface_GetUniquenessValue,
361     Main_DirectDrawSurface_ChangeUniquenessValue,
362     Main_DirectDrawSurface_SetPriority,
363     Main_DirectDrawSurface_GetPriority,
364     Main_DirectDrawSurface_SetLOD,
365     Main_DirectDrawSurface_GetLOD
366 };