Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
6.3 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: vwport.c
  6. * Content: Direct3D viewport functions
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. /*
  12. * Create an api for the Direct3DViewport object
  13. */
  14. #include "drawprim.hpp"
  15. #include "ddibase.h"
  16. //---------------------------------------------------------------------
  17. // Update pre-computed constants related to viewport
  18. //
  19. // This functions should be called every time the viewport parameters are
  20. // changed
  21. //
  22. // Notes:
  23. // 1. scaleY and offsetY are computed to flip Y axes from up to down.
  24. // 2. Mclip matrix is computed multiplied by Mshift matrix
  25. //
  26. const D3DVALUE SMALL_NUMBER = 0.000001f;
  27. void
  28. UpdateViewportCache(LPD3DHAL device, D3DVIEWPORT8 *data)
  29. {
  30. #if DBG
  31. // Bail if we are going to cause any divide by zero exceptions.
  32. // The likely reason is that we have a bogus viewport set by
  33. // TLVertex execute buffer app.
  34. if (data->Width == 0 || data->Height == 0)
  35. {
  36. D3D_ERR("Viewport width or height is zero");
  37. throw D3DERR_INVALIDCALL;
  38. }
  39. if (data->MaxZ < 0 ||
  40. data->MinZ < 0 ||
  41. data->MaxZ > 1 ||
  42. data->MinZ > 1)
  43. {
  44. D3D_ERR("dvMaxZ and dvMinZ should be between 0 and 1");
  45. throw D3DERR_INVALIDCALL;
  46. }
  47. if (data->MaxZ < data->MinZ)
  48. {
  49. D3D_ERR("dvMaxZ should not be smaller than dvMinZ");
  50. throw D3DERR_INVALIDCALL;
  51. }
  52. #endif // DBG
  53. const D3DVALUE eps = 0.001f;
  54. if (data->MaxZ - data->MinZ < eps)
  55. {
  56. // When we clip, we transform vertices from the screen space to the
  57. // clipping space. With the above condition it is impossible. So we do
  58. // a little hack here by setting dvMinZ and dvMaxZ to different values
  59. if (data->MaxZ >= 0.5f)
  60. data->MinZ = data->MaxZ - eps;
  61. else
  62. data->MaxZ = data->MinZ + eps;
  63. }
  64. D3DFE_VIEWPORTCACHE *cache = &device->m_pv->vcache;
  65. cache->dvX = D3DVAL(data->X);
  66. cache->dvY = D3DVAL(data->Y);
  67. cache->dvWidth = D3DVAL(data->Width);
  68. cache->dvHeight = D3DVAL(data->Height);
  69. cache->scaleX = cache->dvWidth;
  70. cache->scaleY = - cache->dvHeight;
  71. cache->scaleZ = D3DVAL(data->MaxZ - data->MinZ);
  72. cache->offsetX = cache->dvX;
  73. cache->offsetY = cache->dvY + cache->dvHeight;
  74. cache->offsetZ = D3DVAL(data->MinZ);
  75. // Small offset is added to prevent generation of negative screen
  76. // coordinates (this could happen because of precision errors).
  77. cache->offsetX += SMALL_NUMBER;
  78. cache->offsetY += SMALL_NUMBER;
  79. cache->scaleXi = D3DVAL(1) / cache->scaleX;
  80. cache->scaleYi = D3DVAL(1) / cache->scaleY;
  81. cache->scaleZi = D3DVAL(1) / cache->scaleZ;
  82. cache->minX = cache->dvX;
  83. cache->maxX = cache->dvX + cache->dvWidth;
  84. cache->minY = cache->dvY;
  85. cache->maxY = cache->dvY + cache->dvHeight;
  86. cache->minXi = FTOI(cache->minX);
  87. cache->maxXi = FTOI(cache->maxX);
  88. cache->minYi = FTOI(cache->minY);
  89. cache->maxYi = FTOI(cache->maxY);
  90. if (device->m_pv->dwDeviceFlags & D3DDEV_GUARDBAND)
  91. {
  92. const D3DCAPS8 *pCaps = device->GetD3DCaps();
  93. // Because we clip by guard band window we have to use its extents
  94. cache->minXgb = pCaps->GuardBandLeft;
  95. cache->maxXgb = pCaps->GuardBandRight;
  96. cache->minYgb = pCaps->GuardBandTop;
  97. cache->maxYgb = pCaps->GuardBandBottom;
  98. D3DVALUE w = 2.0f / cache->dvWidth;
  99. D3DVALUE h = 2.0f / cache->dvHeight;
  100. D3DVALUE ax1 = -(pCaps->GuardBandLeft - cache->dvX) * w + 1.0f;
  101. D3DVALUE ax2 = (pCaps->GuardBandRight - cache->dvX) * w - 1.0f;
  102. D3DVALUE ay1 = (pCaps->GuardBandBottom - cache->dvY) * h - 1.0f;
  103. D3DVALUE ay2 = -(pCaps->GuardBandTop - cache->dvY) * h + 1.0f;
  104. cache->gb11 = 2.0f / (ax1 + ax2);
  105. cache->gb41 = cache->gb11 * (ax1 - 1.0f) * 0.5f;
  106. cache->gb22 = 2.0f / (ay1 + ay2);
  107. cache->gb42 = cache->gb22 * (ay1 - 1.0f) * 0.5f;
  108. cache->Kgbx1 = 0.5f * (1.0f - ax1);
  109. cache->Kgbx2 = 0.5f * (1.0f + ax2);
  110. cache->Kgby1 = 0.5f * (1.0f - ay1);
  111. cache->Kgby2 = 0.5f * (1.0f + ay2);
  112. }
  113. else
  114. {
  115. cache->minXgb = cache->minX;
  116. cache->maxXgb = cache->maxX;
  117. cache->minYgb = cache->minY;
  118. cache->maxYgb = cache->maxY;
  119. }
  120. }
  121. //---------------------------------------------------------------------
  122. #undef DPF_MODNAME
  123. #define DPF_MODNAME "CD3DBase::CheckViewport"
  124. void CD3DBase::CheckViewport(CONST D3DVIEWPORT8* lpData)
  125. {
  126. // We have to check parameters here, because viewport could be changed
  127. // after creating a state set
  128. DWORD uSurfWidth,uSurfHeight;
  129. D3DSURFACE_DESC desc = this->RenderTarget()->InternalGetDesc();
  130. uSurfWidth = desc.Width;
  131. uSurfHeight = desc.Height;
  132. if (lpData->X > uSurfWidth ||
  133. lpData->Y > uSurfHeight ||
  134. lpData->X + lpData->Width > uSurfWidth ||
  135. lpData->Y + lpData->Height > uSurfHeight)
  136. {
  137. D3D_THROW(D3DERR_INVALIDCALL, "Viewport outside the render target surface");
  138. }
  139. }
  140. //---------------------------------------------------------------------
  141. #undef DPF_MODNAME
  142. #define DPF_MODNAME "CD3DHal::SetViewportI"
  143. void CD3DHal::SetViewportI(CONST D3DVIEWPORT8* lpData)
  144. {
  145. // We check viewport here, because the render target could have been
  146. // changed after a state block is created
  147. CheckViewport(lpData);
  148. m_Viewport = *lpData;
  149. // Update front-end data
  150. UpdateViewportCache(this, &this->m_Viewport);
  151. if (!(m_dwRuntimeFlags & D3DRT_EXECUTESTATEMODE))
  152. m_pDDI->SetViewport(&m_Viewport);
  153. }
  154. //---------------------------------------------------------------------
  155. #undef DPF_MODNAME
  156. #define DPF_MODNAME "CD3DHal::GetViewport"
  157. HRESULT
  158. D3DAPI CD3DHal::GetViewport(D3DVIEWPORT8* lpData)
  159. {
  160. API_ENTER(this); // Takes D3D Lock if necessary
  161. if (!VALID_WRITEPTR(lpData, sizeof(*lpData)))
  162. {
  163. D3D_ERR( "Invalid viewport pointer. GetViewport failed." );
  164. return D3DERR_INVALIDCALL;
  165. }
  166. *lpData = this->m_Viewport;
  167. return (D3D_OK);
  168. }