Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenviewport.c
Go to the documentation of this file.
00001 /* Direct3D Viewport 00002 * Copyright (c) 1998 Lionel ULMER 00003 * Copyright (c) 2006-2007 Stefan DÖSINGER 00004 * 00005 * This file contains the implementation of Direct3DViewport2. 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "config.h" 00023 #include "wine/port.h" 00024 00025 #include "ddraw_private.h" 00026 00027 WINE_DEFAULT_DEBUG_CHANNEL(ddraw); 00028 00029 /***************************************************************************** 00030 * Helper functions 00031 *****************************************************************************/ 00032 00033 static void update_clip_space(IDirect3DDeviceImpl *device, 00034 struct wined3d_vec3 *scale, struct wined3d_vec3 *offset) 00035 { 00036 D3DMATRIX clip_space = 00037 { 00038 scale->x, 0.0f, 0.0f, 0.0f, 00039 0.0f, scale->y, 0.0f, 0.0f, 00040 0.0f, 0.0f, scale->z, 0.0f, 00041 offset->x, offset->y, offset->z, 1.0f, 00042 }; 00043 D3DMATRIX projection; 00044 HRESULT hr; 00045 00046 multiply_matrix(&projection, &clip_space, &device->legacy_projection); 00047 hr = wined3d_device_set_transform(device->wined3d_device, 00048 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection); 00049 if (SUCCEEDED(hr)) 00050 device->legacy_clipspace = clip_space; 00051 } 00052 00053 /***************************************************************************** 00054 * viewport_activate 00055 * 00056 * activates the viewport using IDirect3DDevice7::SetViewport 00057 * 00058 *****************************************************************************/ 00059 void viewport_activate(IDirect3DViewportImpl *This, BOOL ignore_lights) 00060 { 00061 struct wined3d_vec3 scale, offset; 00062 D3DVIEWPORT7 vp; 00063 00064 if (!ignore_lights) 00065 { 00066 IDirect3DLightImpl *light; 00067 00068 /* Activate all the lights associated with this context */ 00069 LIST_FOR_EACH_ENTRY(light, &This->light_list, IDirect3DLightImpl, entry) 00070 { 00071 light_activate(light); 00072 } 00073 } 00074 00075 /* And copy the values in the structure used by the device */ 00076 if (This->use_vp2) 00077 { 00078 vp.dwX = This->viewports.vp2.dwX; 00079 vp.dwY = This->viewports.vp2.dwY; 00080 vp.dwHeight = This->viewports.vp2.dwHeight; 00081 vp.dwWidth = This->viewports.vp2.dwWidth; 00082 vp.dvMinZ = 0.0f; 00083 vp.dvMaxZ = 1.0f; 00084 00085 scale.x = 2.0f / This->viewports.vp2.dvClipWidth; 00086 scale.y = 2.0f / This->viewports.vp2.dvClipHeight; 00087 scale.z = 1.0f / (This->viewports.vp2.dvMaxZ - This->viewports.vp2.dvMinZ); 00088 offset.x = -2.0f * This->viewports.vp2.dvClipX / This->viewports.vp2.dvClipWidth - 1.0f; 00089 offset.y = -2.0f * This->viewports.vp2.dvClipY / This->viewports.vp2.dvClipHeight + 1.0f; 00090 offset.z = -This->viewports.vp2.dvMinZ / (This->viewports.vp2.dvMaxZ - This->viewports.vp2.dvMinZ); 00091 } 00092 else 00093 { 00094 vp.dwX = This->viewports.vp1.dwX; 00095 vp.dwY = This->viewports.vp1.dwY; 00096 vp.dwHeight = This->viewports.vp1.dwHeight; 00097 vp.dwWidth = This->viewports.vp1.dwWidth; 00098 vp.dvMinZ = 0.0f; 00099 vp.dvMaxZ = 1.0f; 00100 00101 scale.x = 2.0f * This->viewports.vp1.dvScaleX / This->viewports.vp1.dwWidth; 00102 scale.y = 2.0f * This->viewports.vp1.dvScaleY / This->viewports.vp1.dwHeight; 00103 scale.z = 1.0f; 00104 offset.x = 0.0f; 00105 offset.y = 0.0f; 00106 offset.z = 0.0f; 00107 } 00108 00109 update_clip_space(This->active_device, &scale, &offset); 00110 IDirect3DDevice7_SetViewport(&This->active_device->IDirect3DDevice7_iface, &vp); 00111 } 00112 00113 /***************************************************************************** 00114 * _dump_D3DVIEWPORT, _dump_D3DVIEWPORT2 00115 * 00116 * Writes viewport information to TRACE 00117 * 00118 *****************************************************************************/ 00119 static void _dump_D3DVIEWPORT(const D3DVIEWPORT *lpvp) 00120 { 00121 TRACE(" - dwSize = %d dwX = %d dwY = %d\n", 00122 lpvp->dwSize, lpvp->dwX, lpvp->dwY); 00123 TRACE(" - dwWidth = %d dwHeight = %d\n", 00124 lpvp->dwWidth, lpvp->dwHeight); 00125 TRACE(" - dvScaleX = %f dvScaleY = %f\n", 00126 lpvp->dvScaleX, lpvp->dvScaleY); 00127 TRACE(" - dvMaxX = %f dvMaxY = %f\n", 00128 lpvp->dvMaxX, lpvp->dvMaxY); 00129 TRACE(" - dvMinZ = %f dvMaxZ = %f\n", 00130 lpvp->dvMinZ, lpvp->dvMaxZ); 00131 } 00132 00133 static void _dump_D3DVIEWPORT2(const D3DVIEWPORT2 *lpvp) 00134 { 00135 TRACE(" - dwSize = %d dwX = %d dwY = %d\n", 00136 lpvp->dwSize, lpvp->dwX, lpvp->dwY); 00137 TRACE(" - dwWidth = %d dwHeight = %d\n", 00138 lpvp->dwWidth, lpvp->dwHeight); 00139 TRACE(" - dvClipX = %f dvClipY = %f\n", 00140 lpvp->dvClipX, lpvp->dvClipY); 00141 TRACE(" - dvClipWidth = %f dvClipHeight = %f\n", 00142 lpvp->dvClipWidth, lpvp->dvClipHeight); 00143 TRACE(" - dvMinZ = %f dvMaxZ = %f\n", 00144 lpvp->dvMinZ, lpvp->dvMaxZ); 00145 } 00146 00147 static inline IDirect3DViewportImpl *impl_from_IDirect3DViewport3(IDirect3DViewport3 *iface) 00148 { 00149 return CONTAINING_RECORD(iface, IDirect3DViewportImpl, IDirect3DViewport3_iface); 00150 } 00151 00152 /***************************************************************************** 00153 * IUnknown Methods. 00154 *****************************************************************************/ 00155 00156 /***************************************************************************** 00157 * IDirect3DViewport3::QueryInterface 00158 * 00159 * A normal QueryInterface. Can query all interface versions and the 00160 * IUnknown interface. The VTables of the different versions 00161 * are equal 00162 * 00163 * Params: 00164 * refiid: Interface id queried for 00165 * obj: Address to write the interface pointer to 00166 * 00167 * Returns: 00168 * S_OK on success. 00169 * E_NOINTERFACE if the requested interface wasn't found 00170 * 00171 *****************************************************************************/ 00172 static HRESULT WINAPI IDirect3DViewportImpl_QueryInterface(IDirect3DViewport3 *iface, REFIID riid, void **object) 00173 { 00174 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); 00175 00176 if (IsEqualGUID(&IID_IDirect3DViewport3, riid) 00177 || IsEqualGUID(&IID_IDirect3DViewport2, riid) 00178 || IsEqualGUID(&IID_IDirect3DViewport, riid) 00179 || IsEqualGUID(&IID_IUnknown, riid)) 00180 { 00181 IDirect3DViewport3_AddRef(iface); 00182 *object = iface; 00183 return S_OK; 00184 } 00185 00186 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); 00187 00188 *object = NULL; 00189 return E_NOINTERFACE; 00190 } 00191 00192 /***************************************************************************** 00193 * IDirect3DViewport3::AddRef 00194 * 00195 * Increases the refcount. 00196 * 00197 * Returns: 00198 * The new refcount 00199 * 00200 *****************************************************************************/ 00201 static ULONG WINAPI 00202 IDirect3DViewportImpl_AddRef(IDirect3DViewport3 *iface) 00203 { 00204 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00205 ULONG ref = InterlockedIncrement(&This->ref); 00206 00207 TRACE("%p increasing refcount to %u.\n", This, ref); 00208 00209 return ref; 00210 } 00211 00212 /***************************************************************************** 00213 * IDirect3DViewport3::Release 00214 * 00215 * Reduces the refcount. If it falls to 0, the interface is released 00216 * 00217 * Returns: 00218 * The new refcount 00219 * 00220 *****************************************************************************/ 00221 static ULONG WINAPI 00222 IDirect3DViewportImpl_Release(IDirect3DViewport3 *iface) 00223 { 00224 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00225 ULONG ref = InterlockedDecrement(&This->ref); 00226 00227 TRACE("%p decreasing refcount to %u.\n", This, ref); 00228 00229 if (!ref) { 00230 HeapFree(GetProcessHeap(), 0, This); 00231 return 0; 00232 } 00233 return ref; 00234 } 00235 00236 /***************************************************************************** 00237 * IDirect3DViewport Methods. 00238 *****************************************************************************/ 00239 00240 /***************************************************************************** 00241 * IDirect3DViewport3::Initialize 00242 * 00243 * No-op initialization. 00244 * 00245 * Params: 00246 * Direct3D: The direct3D device this viewport is assigned to 00247 * 00248 * Returns: 00249 * DDERR_ALREADYINITIALIZED 00250 * 00251 *****************************************************************************/ 00252 static HRESULT WINAPI 00253 IDirect3DViewportImpl_Initialize(IDirect3DViewport3 *iface, 00254 IDirect3D *Direct3D) 00255 { 00256 TRACE("iface %p, d3d %p.\n", iface, Direct3D); 00257 00258 return DDERR_ALREADYINITIALIZED; 00259 } 00260 00261 /***************************************************************************** 00262 * IDirect3DViewport3::GetViewport 00263 * 00264 * Returns the viewport data assigned to this viewport interface 00265 * 00266 * Params: 00267 * Data: Address to store the data 00268 * 00269 * Returns: 00270 * D3D_OK on success 00271 * DDERR_INVALIDPARAMS if Data is NULL 00272 * 00273 *****************************************************************************/ 00274 static HRESULT WINAPI 00275 IDirect3DViewportImpl_GetViewport(IDirect3DViewport3 *iface, 00276 D3DVIEWPORT *lpData) 00277 { 00278 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00279 DWORD dwSize; 00280 00281 TRACE("iface %p, data %p.\n", iface, lpData); 00282 00283 wined3d_mutex_lock(); 00284 00285 dwSize = lpData->dwSize; 00286 memset(lpData, 0, dwSize); 00287 if (!This->use_vp2) 00288 memcpy(lpData, &(This->viewports.vp1), dwSize); 00289 else { 00290 D3DVIEWPORT vp1; 00291 vp1.dwSize = sizeof(vp1); 00292 vp1.dwX = This->viewports.vp2.dwX; 00293 vp1.dwY = This->viewports.vp2.dwY; 00294 vp1.dwWidth = This->viewports.vp2.dwWidth; 00295 vp1.dwHeight = This->viewports.vp2.dwHeight; 00296 vp1.dvMaxX = 0.0; 00297 vp1.dvMaxY = 0.0; 00298 vp1.dvScaleX = 0.0; 00299 vp1.dvScaleY = 0.0; 00300 vp1.dvMinZ = This->viewports.vp2.dvMinZ; 00301 vp1.dvMaxZ = This->viewports.vp2.dvMaxZ; 00302 memcpy(lpData, &vp1, dwSize); 00303 } 00304 00305 if (TRACE_ON(ddraw)) 00306 { 00307 TRACE(" returning D3DVIEWPORT :\n"); 00308 _dump_D3DVIEWPORT(lpData); 00309 } 00310 00311 wined3d_mutex_unlock(); 00312 00313 return DD_OK; 00314 } 00315 00316 /***************************************************************************** 00317 * IDirect3DViewport3::SetViewport 00318 * 00319 * Sets the viewport information for this interface 00320 * 00321 * Params: 00322 * lpData: Viewport to set 00323 * 00324 * Returns: 00325 * D3D_OK on success 00326 * DDERR_INVALIDPARAMS if Data is NULL 00327 * 00328 *****************************************************************************/ 00329 static HRESULT WINAPI 00330 IDirect3DViewportImpl_SetViewport(IDirect3DViewport3 *iface, 00331 D3DVIEWPORT *lpData) 00332 { 00333 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00334 IDirect3DViewport3 *current_viewport; 00335 00336 TRACE("iface %p, data %p.\n", iface, lpData); 00337 00338 if (TRACE_ON(ddraw)) 00339 { 00340 TRACE(" getting D3DVIEWPORT :\n"); 00341 _dump_D3DVIEWPORT(lpData); 00342 } 00343 00344 wined3d_mutex_lock(); 00345 00346 This->use_vp2 = 0; 00347 memset(&(This->viewports.vp1), 0, sizeof(This->viewports.vp1)); 00348 memcpy(&(This->viewports.vp1), lpData, lpData->dwSize); 00349 00350 /* Tests on two games show that these values are never used properly so override 00351 them with proper ones :-) 00352 */ 00353 This->viewports.vp1.dvMinZ = 0.0; 00354 This->viewports.vp1.dvMaxZ = 1.0; 00355 00356 if (This->active_device) { 00357 IDirect3DDevice3 *d3d_device3 = &This->active_device->IDirect3DDevice3_iface; 00358 IDirect3DDevice3_GetCurrentViewport(d3d_device3, ¤t_viewport); 00359 if (current_viewport) 00360 { 00361 if (current_viewport == iface) viewport_activate(This, FALSE); 00362 IDirect3DViewport3_Release(current_viewport); 00363 } 00364 } 00365 00366 wined3d_mutex_unlock(); 00367 00368 return DD_OK; 00369 } 00370 00371 /***************************************************************************** 00372 * IDirect3DViewport3::TransformVertices 00373 * 00374 * Transforms vertices by the transformation matrix. 00375 * 00376 * This function is pretty similar to IDirect3DVertexBuffer7::ProcessVertices, 00377 * so it's tempting to forward it to there. However, there are some 00378 * tiny differences. First, the lpOffscreen flag that is reported back, 00379 * then there is the homogeneous vertex that is generated. Also there's a lack 00380 * of FVFs, but still a custom stride. Last, the d3d1 - d3d3 viewport has some 00381 * settings (scale) that d3d7 and wined3d do not have. All in all wrapping to 00382 * ProcessVertices doesn't pay of in terms of wrapper code needed and code 00383 * reused. 00384 * 00385 * Params: 00386 * dwVertexCount: The number of vertices to be transformed 00387 * lpData: Pointer to the vertex data 00388 * dwFlags: D3DTRANSFORM_CLIPPED or D3DTRANSFORM_UNCLIPPED 00389 * lpOffScreen: Set to the clipping plane clipping the vertex, if only one 00390 * vertex is transformed and clipping is on. 0 otherwise 00391 * 00392 * Returns: 00393 * D3D_OK on success 00394 * D3DERR_VIEWPORTHASNODEVICE if the viewport is not assigned to a device 00395 * DDERR_INVALIDPARAMS if no clipping flag is specified 00396 * 00397 *****************************************************************************/ 00398 static HRESULT WINAPI 00399 IDirect3DViewportImpl_TransformVertices(IDirect3DViewport3 *iface, 00400 DWORD dwVertexCount, 00401 D3DTRANSFORMDATA *lpData, 00402 DWORD dwFlags, 00403 DWORD *lpOffScreen) 00404 { 00405 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00406 D3DMATRIX view_mat, world_mat, mat; 00407 float *in; 00408 float *out; 00409 float x, y, z, w; 00410 unsigned int i; 00411 D3DVIEWPORT vp = This->viewports.vp1; 00412 D3DHVERTEX *outH; 00413 00414 TRACE("iface %p, vertex_count %u, vertex_data %p, flags %#x, clip_plane %p.\n", 00415 iface, dwVertexCount, lpData, dwFlags, lpOffScreen); 00416 00417 /* Tests on windows show that Windows crashes when this occurs, 00418 * so don't return the (intuitive) return value 00419 if(!This->active_device) 00420 { 00421 WARN("No device active, returning D3DERR_VIEWPORTHASNODEVICE\n"); 00422 return D3DERR_VIEWPORTHASNODEVICE; 00423 } 00424 */ 00425 00426 if(!(dwFlags & (D3DTRANSFORM_UNCLIPPED | D3DTRANSFORM_CLIPPED))) 00427 { 00428 WARN("No clipping flag passed, returning DDERR_INVALIDPARAMS\n"); 00429 return DDERR_INVALIDPARAMS; 00430 } 00431 00432 00433 wined3d_mutex_lock(); 00434 wined3d_device_get_transform(This->active_device->wined3d_device, 00435 D3DTRANSFORMSTATE_VIEW, (struct wined3d_matrix *)&view_mat); 00436 wined3d_device_get_transform(This->active_device->wined3d_device, 00437 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)&world_mat); 00438 multiply_matrix(&mat, &view_mat, &world_mat); 00439 multiply_matrix(&mat, &This->active_device->legacy_projection, &mat); 00440 00441 in = lpData->lpIn; 00442 out = lpData->lpOut; 00443 outH = lpData->lpHOut; 00444 for(i = 0; i < dwVertexCount; i++) 00445 { 00446 x = (in[0] * mat._11) + (in[1] * mat._21) + (in[2] * mat._31) + (1.0 * mat._41); 00447 y = (in[0] * mat._12) + (in[1] * mat._22) + (in[2] * mat._32) + (1.0 * mat._42); 00448 z = (in[0] * mat._13) + (in[1] * mat._23) + (in[2] * mat._33) + (1.0 * mat._43); 00449 w = (in[0] * mat._14) + (in[1] * mat._24) + (in[2] * mat._34) + (1.0 * mat._44); 00450 00451 if(dwFlags & D3DTRANSFORM_CLIPPED) 00452 { 00453 /* If clipping is enabled, Windows assumes that outH is 00454 * a valid pointer 00455 */ 00456 outH[i].u1.hx = x; outH[i].u2.hy = y; outH[i].u3.hz = z; 00457 00458 outH[i].dwFlags = 0; 00459 if(x * vp.dvScaleX > ((float) vp.dwWidth * 0.5)) 00460 outH[i].dwFlags |= D3DCLIP_RIGHT; 00461 if(x * vp.dvScaleX <= -((float) vp.dwWidth) * 0.5) 00462 outH[i].dwFlags |= D3DCLIP_LEFT; 00463 if(y * vp.dvScaleY > ((float) vp.dwHeight * 0.5)) 00464 outH[i].dwFlags |= D3DCLIP_TOP; 00465 if(y * vp.dvScaleY <= -((float) vp.dwHeight) * 0.5) 00466 outH[i].dwFlags |= D3DCLIP_BOTTOM; 00467 if(z < 0.0) 00468 outH[i].dwFlags |= D3DCLIP_FRONT; 00469 if(z > 1.0) 00470 outH[i].dwFlags |= D3DCLIP_BACK; 00471 00472 if(outH[i].dwFlags) 00473 { 00474 /* Looks like native just drops the vertex, leaves whatever data 00475 * it has in the output buffer and goes on with the next vertex. 00476 * The exact scheme hasn't been figured out yet, but windows 00477 * definitely writes something there. 00478 */ 00479 out[0] = x; 00480 out[1] = y; 00481 out[2] = z; 00482 out[3] = w; 00483 in = (float *) ((char *) in + lpData->dwInSize); 00484 out = (float *) ((char *) out + lpData->dwOutSize); 00485 continue; 00486 } 00487 } 00488 00489 w = 1 / w; 00490 x *= w; y *= w; z *= w; 00491 00492 out[0] = vp.dwWidth / 2 + vp.dwX + x * vp.dvScaleX; 00493 out[1] = vp.dwHeight / 2 + vp.dwY - y * vp.dvScaleY; 00494 out[2] = z; 00495 out[3] = w; 00496 in = (float *) ((char *) in + lpData->dwInSize); 00497 out = (float *) ((char *) out + lpData->dwOutSize); 00498 } 00499 00500 /* According to the d3d test, the offscreen flag is set only 00501 * if exactly one vertex is transformed. Its not documented, 00502 * but the test shows that the lpOffscreen flag is set to the 00503 * flag combination of clipping planes that clips the vertex. 00504 * 00505 * If clipping is requested, Windows assumes that the offscreen 00506 * param is a valid pointer. 00507 */ 00508 if(dwVertexCount == 1 && dwFlags & D3DTRANSFORM_CLIPPED) 00509 { 00510 *lpOffScreen = outH[0].dwFlags; 00511 } 00512 else if(*lpOffScreen) 00513 { 00514 *lpOffScreen = 0; 00515 } 00516 wined3d_mutex_unlock(); 00517 00518 TRACE("All done\n"); 00519 return DD_OK; 00520 } 00521 00522 /***************************************************************************** 00523 * IDirect3DViewport3::LightElements 00524 * 00525 * The DirectX 5.0 sdk says that it's not implemented 00526 * 00527 * Params: 00528 * ? 00529 * 00530 * Returns: 00531 * DDERR_UNSUPPORTED 00532 * 00533 *****************************************************************************/ 00534 static HRESULT WINAPI 00535 IDirect3DViewportImpl_LightElements(IDirect3DViewport3 *iface, 00536 DWORD dwElementCount, 00537 LPD3DLIGHTDATA lpData) 00538 { 00539 TRACE("iface %p, element_count %u, data %p.\n", iface, dwElementCount, lpData); 00540 00541 return DDERR_UNSUPPORTED; 00542 } 00543 00544 /***************************************************************************** 00545 * IDirect3DViewport3::SetBackground 00546 * 00547 * Sets tje background material 00548 * 00549 * Params: 00550 * hMat: Handle from a IDirect3DMaterial interface 00551 * 00552 * Returns: 00553 * D3D_OK on success 00554 * 00555 *****************************************************************************/ 00556 static HRESULT WINAPI 00557 IDirect3DViewportImpl_SetBackground(IDirect3DViewport3 *iface, 00558 D3DMATERIALHANDLE hMat) 00559 { 00560 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00561 IDirect3DMaterialImpl *m; 00562 00563 TRACE("iface %p, material %#x.\n", iface, hMat); 00564 00565 wined3d_mutex_lock(); 00566 00567 if (!hMat) 00568 { 00569 This->background = NULL; 00570 TRACE("Setting background to NULL\n"); 00571 wined3d_mutex_unlock(); 00572 return D3D_OK; 00573 } 00574 00575 m = ddraw_get_object(&This->ddraw->d3ddevice->handle_table, hMat - 1, DDRAW_HANDLE_MATERIAL); 00576 if (!m) 00577 { 00578 WARN("Invalid material handle.\n"); 00579 wined3d_mutex_unlock(); 00580 return DDERR_INVALIDPARAMS; 00581 } 00582 00583 TRACE("Setting background color : %.8e %.8e %.8e %.8e.\n", 00584 m->mat.u.diffuse.u1.r, m->mat.u.diffuse.u2.g, 00585 m->mat.u.diffuse.u3.b, m->mat.u.diffuse.u4.a); 00586 This->background = m; 00587 00588 wined3d_mutex_unlock(); 00589 00590 return D3D_OK; 00591 } 00592 00593 /***************************************************************************** 00594 * IDirect3DViewport3::GetBackground 00595 * 00596 * Returns the material handle assigned to the background of the viewport 00597 * 00598 * Params: 00599 * lphMat: Address to store the handle 00600 * lpValid: is set to FALSE if no background is set, TRUE if one is set 00601 * 00602 * Returns: 00603 * D3D_OK 00604 * 00605 *****************************************************************************/ 00606 static HRESULT WINAPI 00607 IDirect3DViewportImpl_GetBackground(IDirect3DViewport3 *iface, 00608 D3DMATERIALHANDLE *lphMat, 00609 BOOL *lpValid) 00610 { 00611 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00612 00613 TRACE("iface %p, material %p, valid %p.\n", iface, lphMat, lpValid); 00614 00615 wined3d_mutex_lock(); 00616 if(lpValid) 00617 { 00618 *lpValid = This->background != NULL; 00619 } 00620 if(lphMat) 00621 { 00622 if(This->background) 00623 { 00624 *lphMat = This->background->Handle; 00625 } 00626 else 00627 { 00628 *lphMat = 0; 00629 } 00630 } 00631 wined3d_mutex_unlock(); 00632 00633 return D3D_OK; 00634 } 00635 00636 /***************************************************************************** 00637 * IDirect3DViewport3::SetBackgroundDepth 00638 * 00639 * Sets a surface that represents the background depth. It's contents are 00640 * used to set the depth buffer in IDirect3DViewport3::Clear 00641 * 00642 * Params: 00643 * lpDDSurface: Surface to set 00644 * 00645 * Returns: D3D_OK, because it's a stub 00646 * 00647 *****************************************************************************/ 00648 static HRESULT WINAPI 00649 IDirect3DViewportImpl_SetBackgroundDepth(IDirect3DViewport3 *iface, 00650 IDirectDrawSurface *lpDDSurface) 00651 { 00652 FIXME("iface %p, surface %p stub!\n", iface, lpDDSurface); 00653 00654 return D3D_OK; 00655 } 00656 00657 /***************************************************************************** 00658 * IDirect3DViewport3::GetBackgroundDepth 00659 * 00660 * Returns the surface that represents the depth field 00661 * 00662 * Params: 00663 * lplpDDSurface: Address to store the interface pointer 00664 * lpValid: Set to TRUE if a depth is assigned, FALSE otherwise 00665 * 00666 * Returns: 00667 * D3D_OK, because it's a stub 00668 * (DDERR_INVALIDPARAMS if DDSurface of Valid is NULL) 00669 * 00670 *****************************************************************************/ 00671 static HRESULT WINAPI 00672 IDirect3DViewportImpl_GetBackgroundDepth(IDirect3DViewport3 *iface, 00673 IDirectDrawSurface **lplpDDSurface, 00674 LPBOOL lpValid) 00675 { 00676 FIXME("iface %p, surface %p, valid %p stub!\n", iface, lplpDDSurface, lpValid); 00677 00678 return DD_OK; 00679 } 00680 00681 /***************************************************************************** 00682 * IDirect3DViewport3::Clear 00683 * 00684 * Clears the render target and / or the z buffer 00685 * 00686 * Params: 00687 * dwCount: The amount of rectangles to clear. If 0, the whole buffer is 00688 * cleared 00689 * lpRects: Pointer to the array of rectangles. If NULL, Count must be 0 00690 * dwFlags: D3DCLEAR_ZBUFFER and / or D3DCLEAR_TARGET 00691 * 00692 * Returns: 00693 * D3D_OK on success 00694 * D3DERR_VIEWPORTHASNODEVICE if there's no active device 00695 * The return value of IDirect3DDevice7::Clear 00696 * 00697 *****************************************************************************/ 00698 static HRESULT WINAPI IDirect3DViewportImpl_Clear(IDirect3DViewport3 *iface, 00699 DWORD dwCount, D3DRECT *lpRects, DWORD dwFlags) 00700 { 00701 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00702 DWORD color = 0x00000000; 00703 HRESULT hr; 00704 IDirect3DViewport3 *current_viewport; 00705 IDirect3DDevice3 *d3d_device3; 00706 00707 TRACE("iface %p, rect_count %u, rects %p, flags %#x.\n", iface, dwCount, lpRects, dwFlags); 00708 00709 if (This->active_device == NULL) { 00710 ERR(" Trying to clear a viewport not attached to a device !\n"); 00711 return D3DERR_VIEWPORTHASNODEVICE; 00712 } 00713 d3d_device3 = &This->active_device->IDirect3DDevice3_iface; 00714 00715 wined3d_mutex_lock(); 00716 00717 if (dwFlags & D3DCLEAR_TARGET) { 00718 if (This->background == NULL) { 00719 ERR(" Trying to clear the color buffer without background material !\n"); 00720 } 00721 else 00722 { 00723 color = ((int)((This->background->mat.u.diffuse.u1.r) * 255) << 16) 00724 | ((int) ((This->background->mat.u.diffuse.u2.g) * 255) << 8) 00725 | ((int) ((This->background->mat.u.diffuse.u3.b) * 255) << 0) 00726 | ((int) ((This->background->mat.u.diffuse.u4.a) * 255) << 24); 00727 } 00728 } 00729 00730 /* Need to temporarily activate viewport to clear it. Previously active one will be restored 00731 afterwards. */ 00732 viewport_activate(This, TRUE); 00733 00734 hr = IDirect3DDevice7_Clear(&This->active_device->IDirect3DDevice7_iface, dwCount, lpRects, 00735 dwFlags & (D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET), color, 1.0, 0x00000000); 00736 00737 IDirect3DDevice3_GetCurrentViewport(d3d_device3, ¤t_viewport); 00738 if(current_viewport) { 00739 IDirect3DViewportImpl *vp = impl_from_IDirect3DViewport3(current_viewport); 00740 viewport_activate(vp, TRUE); 00741 IDirect3DViewport3_Release(current_viewport); 00742 } 00743 00744 wined3d_mutex_unlock(); 00745 00746 return hr; 00747 } 00748 00749 /***************************************************************************** 00750 * IDirect3DViewport3::AddLight 00751 * 00752 * Adds an light to the viewport 00753 * 00754 * Params: 00755 * lpDirect3DLight: Interface of the light to add 00756 * 00757 * Returns: 00758 * D3D_OK on success 00759 * DDERR_INVALIDPARAMS if Direct3DLight is NULL 00760 * DDERR_INVALIDPARAMS if there are 8 lights or more 00761 * 00762 *****************************************************************************/ 00763 static HRESULT WINAPI IDirect3DViewportImpl_AddLight(IDirect3DViewport3 *iface, 00764 IDirect3DLight *lpDirect3DLight) 00765 { 00766 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00767 IDirect3DLightImpl *lpDirect3DLightImpl = unsafe_impl_from_IDirect3DLight(lpDirect3DLight); 00768 DWORD i = 0; 00769 DWORD map = This->map_lights; 00770 00771 TRACE("iface %p, light %p.\n", iface, lpDirect3DLight); 00772 00773 wined3d_mutex_lock(); 00774 00775 if (This->num_lights >= 8) 00776 { 00777 wined3d_mutex_unlock(); 00778 return DDERR_INVALIDPARAMS; 00779 } 00780 00781 /* Find a light number and update both light and viewports objects accordingly */ 00782 while (map & 1) 00783 { 00784 map >>= 1; 00785 ++i; 00786 } 00787 lpDirect3DLightImpl->dwLightIndex = i; 00788 This->num_lights++; 00789 This->map_lights |= 1<<i; 00790 00791 /* Add the light in the 'linked' chain */ 00792 list_add_head(&This->light_list, &lpDirect3DLightImpl->entry); 00793 IDirect3DLight_AddRef(lpDirect3DLight); 00794 00795 /* Attach the light to the viewport */ 00796 lpDirect3DLightImpl->active_viewport = This; 00797 00798 /* If active, activate the light */ 00799 if (This->active_device) 00800 light_activate(lpDirect3DLightImpl); 00801 00802 wined3d_mutex_unlock(); 00803 00804 return D3D_OK; 00805 } 00806 00807 /***************************************************************************** 00808 * IDirect3DViewport3::DeleteLight 00809 * 00810 * Deletes a light from the viewports' light list 00811 * 00812 * Params: 00813 * lpDirect3DLight: Light to delete 00814 * 00815 * Returns: 00816 * D3D_OK on success 00817 * DDERR_INVALIDPARAMS if the light wasn't found 00818 * 00819 *****************************************************************************/ 00820 static HRESULT WINAPI IDirect3DViewportImpl_DeleteLight(IDirect3DViewport3 *iface, 00821 IDirect3DLight *lpDirect3DLight) 00822 { 00823 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00824 IDirect3DLightImpl *l = unsafe_impl_from_IDirect3DLight(lpDirect3DLight); 00825 00826 TRACE("iface %p, light %p.\n", iface, lpDirect3DLight); 00827 00828 wined3d_mutex_lock(); 00829 00830 if (l->active_viewport != This) 00831 { 00832 WARN("Light %p active viewport is %p.\n", l, l->active_viewport); 00833 wined3d_mutex_unlock(); 00834 return DDERR_INVALIDPARAMS; 00835 } 00836 00837 light_deactivate(l); 00838 list_remove(&l->entry); 00839 l->active_viewport = NULL; 00840 IDirect3DLight_Release(lpDirect3DLight); 00841 --This->num_lights; 00842 This->map_lights &= ~(1 << l->dwLightIndex); 00843 00844 wined3d_mutex_unlock(); 00845 00846 return D3D_OK; 00847 } 00848 00849 /***************************************************************************** 00850 * IDirect3DViewport::NextLight 00851 * 00852 * Enumerates the lights associated with the viewport 00853 * 00854 * Params: 00855 * lpDirect3DLight: Light to start with 00856 * lplpDirect3DLight: Address to store the successor to 00857 * 00858 * Returns: 00859 * D3D_OK, because it's a stub 00860 * 00861 *****************************************************************************/ 00862 static HRESULT WINAPI IDirect3DViewportImpl_NextLight(IDirect3DViewport3 *iface, 00863 IDirect3DLight *lpDirect3DLight, IDirect3DLight **lplpDirect3DLight, DWORD dwFlags) 00864 { 00865 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00866 IDirect3DLightImpl *l = unsafe_impl_from_IDirect3DLight(lpDirect3DLight); 00867 struct list *entry; 00868 HRESULT hr; 00869 00870 TRACE("iface %p, light %p, next_light %p, flags %#x.\n", 00871 iface, lpDirect3DLight, lplpDirect3DLight, dwFlags); 00872 00873 if (!lplpDirect3DLight) 00874 return DDERR_INVALIDPARAMS; 00875 00876 wined3d_mutex_lock(); 00877 00878 switch (dwFlags) 00879 { 00880 case D3DNEXT_NEXT: 00881 if (!l || l->active_viewport != This) 00882 { 00883 if (l) 00884 WARN("Light %p active viewport is %p.\n", l, l->active_viewport); 00885 entry = NULL; 00886 } 00887 else 00888 entry = list_next(&This->light_list, &l->entry); 00889 break; 00890 00891 case D3DNEXT_HEAD: 00892 entry = list_head(&This->light_list); 00893 break; 00894 00895 case D3DNEXT_TAIL: 00896 entry = list_tail(&This->light_list); 00897 break; 00898 00899 default: 00900 entry = NULL; 00901 WARN("Invalid flags %#x.\n", dwFlags); 00902 break; 00903 } 00904 00905 if (entry) 00906 { 00907 *lplpDirect3DLight = (IDirect3DLight *)LIST_ENTRY(entry, IDirect3DLightImpl, entry); 00908 IDirect3DLight_AddRef(*lplpDirect3DLight); 00909 hr = D3D_OK; 00910 } 00911 else 00912 { 00913 *lplpDirect3DLight = NULL; 00914 hr = DDERR_INVALIDPARAMS; 00915 } 00916 00917 wined3d_mutex_unlock(); 00918 00919 return hr; 00920 } 00921 00922 /***************************************************************************** 00923 * IDirect3DViewport2 Methods. 00924 *****************************************************************************/ 00925 00926 /***************************************************************************** 00927 * IDirect3DViewport3::GetViewport2 00928 * 00929 * Returns the currently set viewport in a D3DVIEWPORT2 structure. 00930 * Similar to IDirect3DViewport3::GetViewport 00931 * 00932 * Params: 00933 * lpData: Pointer to the structure to fill 00934 * 00935 * Returns: 00936 * D3D_OK on success 00937 * DDERR_INVALIDPARAMS if the viewport was set with 00938 * IDirect3DViewport3::SetViewport 00939 * DDERR_INVALIDPARAMS if Data is NULL 00940 * 00941 *****************************************************************************/ 00942 static HRESULT WINAPI 00943 IDirect3DViewportImpl_GetViewport2(IDirect3DViewport3 *iface, 00944 D3DVIEWPORT2 *lpData) 00945 { 00946 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 00947 DWORD dwSize; 00948 00949 TRACE("iface %p, data %p.\n", iface, lpData); 00950 00951 wined3d_mutex_lock(); 00952 dwSize = lpData->dwSize; 00953 memset(lpData, 0, dwSize); 00954 if (This->use_vp2) 00955 memcpy(lpData, &(This->viewports.vp2), dwSize); 00956 else { 00957 D3DVIEWPORT2 vp2; 00958 vp2.dwSize = sizeof(vp2); 00959 vp2.dwX = This->viewports.vp1.dwX; 00960 vp2.dwY = This->viewports.vp1.dwY; 00961 vp2.dwWidth = This->viewports.vp1.dwWidth; 00962 vp2.dwHeight = This->viewports.vp1.dwHeight; 00963 vp2.dvClipX = 0.0; 00964 vp2.dvClipY = 0.0; 00965 vp2.dvClipWidth = 0.0; 00966 vp2.dvClipHeight = 0.0; 00967 vp2.dvMinZ = This->viewports.vp1.dvMinZ; 00968 vp2.dvMaxZ = This->viewports.vp1.dvMaxZ; 00969 memcpy(lpData, &vp2, dwSize); 00970 } 00971 00972 if (TRACE_ON(ddraw)) 00973 { 00974 TRACE(" returning D3DVIEWPORT2 :\n"); 00975 _dump_D3DVIEWPORT2(lpData); 00976 } 00977 00978 wined3d_mutex_unlock(); 00979 00980 return D3D_OK; 00981 } 00982 00983 /***************************************************************************** 00984 * IDirect3DViewport3::SetViewport2 00985 * 00986 * Sets the viewport from a D3DVIEWPORT2 structure 00987 * 00988 * Params: 00989 * lpData: Viewport to set 00990 * 00991 * Returns: 00992 * D3D_OK on success 00993 * 00994 *****************************************************************************/ 00995 static HRESULT WINAPI 00996 IDirect3DViewportImpl_SetViewport2(IDirect3DViewport3 *iface, 00997 D3DVIEWPORT2 *lpData) 00998 { 00999 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 01000 IDirect3DViewport3 *current_viewport; 01001 01002 TRACE("iface %p, data %p.\n", iface, lpData); 01003 01004 if (TRACE_ON(ddraw)) 01005 { 01006 TRACE(" getting D3DVIEWPORT2 :\n"); 01007 _dump_D3DVIEWPORT2(lpData); 01008 } 01009 01010 wined3d_mutex_lock(); 01011 01012 This->use_vp2 = 1; 01013 memset(&(This->viewports.vp2), 0, sizeof(This->viewports.vp2)); 01014 memcpy(&(This->viewports.vp2), lpData, lpData->dwSize); 01015 01016 if (This->active_device) { 01017 IDirect3DDevice3 *d3d_device3 = &This->active_device->IDirect3DDevice3_iface; 01018 IDirect3DDevice3_GetCurrentViewport(d3d_device3, ¤t_viewport); 01019 if (current_viewport) 01020 { 01021 if (current_viewport == iface) viewport_activate(This, FALSE); 01022 IDirect3DViewport3_Release(current_viewport); 01023 } 01024 } 01025 01026 wined3d_mutex_unlock(); 01027 01028 return D3D_OK; 01029 } 01030 01031 /***************************************************************************** 01032 * IDirect3DViewport3 Methods. 01033 *****************************************************************************/ 01034 01035 /***************************************************************************** 01036 * IDirect3DViewport3::SetBackgroundDepth2 01037 * 01038 * Sets a IDirectDrawSurface4 surface as the background depth surface 01039 * 01040 * Params: 01041 * lpDDS: Surface to set 01042 * 01043 * Returns: 01044 * D3D_OK, because it's stub 01045 * 01046 *****************************************************************************/ 01047 static HRESULT WINAPI 01048 IDirect3DViewportImpl_SetBackgroundDepth2(IDirect3DViewport3 *iface, 01049 IDirectDrawSurface4 *lpDDS) 01050 { 01051 FIXME("iface %p, surface %p stub!\n", iface, lpDDS); 01052 01053 return D3D_OK; 01054 } 01055 01056 /***************************************************************************** 01057 * IDirect3DViewport3::GetBackgroundDepth2 01058 * 01059 * Returns the IDirect3DSurface4 interface to the background depth surface 01060 * 01061 * Params: 01062 * lplpDDS: Address to store the interface pointer at 01063 * lpValid: Set to true if a surface is assigned 01064 * 01065 * Returns: 01066 * D3D_OK because it's a stub 01067 * 01068 *****************************************************************************/ 01069 static HRESULT WINAPI 01070 IDirect3DViewportImpl_GetBackgroundDepth2(IDirect3DViewport3 *iface, 01071 IDirectDrawSurface4 **lplpDDS, 01072 BOOL *lpValid) 01073 { 01074 FIXME("iface %p, surface %p, valid %p stub!\n", iface, lplpDDS, lpValid); 01075 01076 return D3D_OK; 01077 } 01078 01079 /***************************************************************************** 01080 * IDirect3DViewport3::Clear2 01081 * 01082 * Another clearing method 01083 * 01084 * Params: 01085 * Count: Number of rectangles to clear 01086 * Rects: Rectangle array to clear 01087 * Flags: Some flags :) 01088 * Color: Color to fill the render target with 01089 * Z: Value to fill the depth buffer with 01090 * Stencil: Value to fill the stencil bits with 01091 * 01092 * Returns: 01093 * 01094 *****************************************************************************/ 01095 static HRESULT WINAPI 01096 IDirect3DViewportImpl_Clear2(IDirect3DViewport3 *iface, 01097 DWORD dwCount, 01098 LPD3DRECT lpRects, 01099 DWORD dwFlags, 01100 DWORD dwColor, 01101 D3DVALUE dvZ, 01102 DWORD dwStencil) 01103 { 01104 IDirect3DViewportImpl *This = impl_from_IDirect3DViewport3(iface); 01105 HRESULT hr; 01106 IDirect3DViewport3 *current_viewport; 01107 IDirect3DDevice3 *d3d_device3; 01108 01109 TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, depth %.8e, stencil %u.\n", 01110 iface, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil); 01111 01112 wined3d_mutex_lock(); 01113 01114 if (This->active_device == NULL) { 01115 ERR(" Trying to clear a viewport not attached to a device !\n"); 01116 wined3d_mutex_unlock(); 01117 return D3DERR_VIEWPORTHASNODEVICE; 01118 } 01119 d3d_device3 = &This->active_device->IDirect3DDevice3_iface; 01120 /* Need to temporarily activate viewport to clear it. Previously active 01121 * one will be restored afterwards. */ 01122 viewport_activate(This, TRUE); 01123 01124 hr = IDirect3DDevice7_Clear(&This->active_device->IDirect3DDevice7_iface, 01125 dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil); 01126 IDirect3DDevice3_GetCurrentViewport(d3d_device3, ¤t_viewport); 01127 if(current_viewport) { 01128 IDirect3DViewportImpl *vp = impl_from_IDirect3DViewport3(current_viewport); 01129 viewport_activate(vp, TRUE); 01130 IDirect3DViewport3_Release(current_viewport); 01131 } 01132 01133 wined3d_mutex_unlock(); 01134 01135 return hr; 01136 } 01137 01138 /***************************************************************************** 01139 * The VTable 01140 *****************************************************************************/ 01141 01142 static const struct IDirect3DViewport3Vtbl d3d_viewport_vtbl = 01143 { 01144 /*** IUnknown Methods ***/ 01145 IDirect3DViewportImpl_QueryInterface, 01146 IDirect3DViewportImpl_AddRef, 01147 IDirect3DViewportImpl_Release, 01148 /*** IDirect3DViewport Methods */ 01149 IDirect3DViewportImpl_Initialize, 01150 IDirect3DViewportImpl_GetViewport, 01151 IDirect3DViewportImpl_SetViewport, 01152 IDirect3DViewportImpl_TransformVertices, 01153 IDirect3DViewportImpl_LightElements, 01154 IDirect3DViewportImpl_SetBackground, 01155 IDirect3DViewportImpl_GetBackground, 01156 IDirect3DViewportImpl_SetBackgroundDepth, 01157 IDirect3DViewportImpl_GetBackgroundDepth, 01158 IDirect3DViewportImpl_Clear, 01159 IDirect3DViewportImpl_AddLight, 01160 IDirect3DViewportImpl_DeleteLight, 01161 IDirect3DViewportImpl_NextLight, 01162 /*** IDirect3DViewport2 Methods ***/ 01163 IDirect3DViewportImpl_GetViewport2, 01164 IDirect3DViewportImpl_SetViewport2, 01165 /*** IDirect3DViewport3 Methods ***/ 01166 IDirect3DViewportImpl_SetBackgroundDepth2, 01167 IDirect3DViewportImpl_GetBackgroundDepth2, 01168 IDirect3DViewportImpl_Clear2, 01169 }; 01170 01171 IDirect3DViewportImpl *unsafe_impl_from_IDirect3DViewport3(IDirect3DViewport3 *iface) 01172 { 01173 if (!iface) return NULL; 01174 assert(iface->lpVtbl == &d3d_viewport_vtbl); 01175 return CONTAINING_RECORD(iface, IDirect3DViewportImpl, IDirect3DViewport3_iface); 01176 } 01177 01178 IDirect3DViewportImpl *unsafe_impl_from_IDirect3DViewport2(IDirect3DViewport2 *iface) 01179 { 01180 /* IDirect3DViewport and IDirect3DViewport3 use the same iface. */ 01181 if (!iface) return NULL; 01182 assert(iface->lpVtbl == (IDirect3DViewport2Vtbl *)&d3d_viewport_vtbl); 01183 return CONTAINING_RECORD(iface, IDirect3DViewportImpl, IDirect3DViewport3_iface); 01184 } 01185 01186 IDirect3DViewportImpl *unsafe_impl_from_IDirect3DViewport(IDirect3DViewport *iface) 01187 { 01188 /* IDirect3DViewport and IDirect3DViewport3 use the same iface. */ 01189 if (!iface) return NULL; 01190 assert(iface->lpVtbl == (IDirect3DViewportVtbl *)&d3d_viewport_vtbl); 01191 return CONTAINING_RECORD(iface, IDirect3DViewportImpl, IDirect3DViewport3_iface); 01192 } 01193 01194 void d3d_viewport_init(IDirect3DViewportImpl *viewport, IDirectDrawImpl *ddraw) 01195 { 01196 viewport->IDirect3DViewport3_iface.lpVtbl = &d3d_viewport_vtbl; 01197 viewport->ref = 1; 01198 viewport->ddraw = ddraw; 01199 viewport->use_vp2 = 0xff; 01200 list_init(&viewport->light_list); 01201 } Generated on Sun May 27 2012 04:22:17 for ReactOS by
1.7.6.1
|