PageRenderTime 25ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/ThirdParty/ANGLE/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp

https://gitlab.com/paretje/qtwebkit
C++ | 422 lines | 336 code | 67 blank | 19 comment | 64 complexity | c69f8cd8e53923bd904f2022ca543c9b MD5 | raw file
  1. //
  2. // Copyright 2014 The ANGLE Project Authors. All rights reserved.
  3. // Use of this source code is governed by a BSD-style license that can be
  4. // found in the LICENSE file.
  5. //
  6. // Framebuffer9.cpp: Implements the Framebuffer9 class.
  7. #include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
  8. #include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
  9. #include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
  10. #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
  11. #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
  12. #include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
  13. #include "libANGLE/renderer/d3d/TextureD3D.h"
  14. #include "libANGLE/formatutils.h"
  15. #include "libANGLE/Framebuffer.h"
  16. #include "libANGLE/FramebufferAttachment.h"
  17. #include "libANGLE/Texture.h"
  18. namespace rx
  19. {
  20. Framebuffer9::Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer)
  21. : FramebufferD3D(data, renderer),
  22. mRenderer(renderer)
  23. {
  24. ASSERT(mRenderer != nullptr);
  25. }
  26. Framebuffer9::~Framebuffer9()
  27. {
  28. }
  29. gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &clearParams)
  30. {
  31. const gl::FramebufferAttachment *colorAttachment = mData.getColorAttachment(0);
  32. const gl::FramebufferAttachment *depthStencilAttachment = mData.getDepthOrStencilAttachment();
  33. gl::Error error = mRenderer->applyRenderTarget(colorAttachment, depthStencilAttachment);
  34. if (error.isError())
  35. {
  36. return error;
  37. }
  38. float nearZ = state.getNearPlane();
  39. float farZ = state.getFarPlane();
  40. mRenderer->setViewport(state.getViewport(), nearZ, farZ, GL_TRIANGLES, state.getRasterizerState().frontFace, true);
  41. mRenderer->setScissorRectangle(state.getScissor(), state.isScissorTestEnabled());
  42. return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment);
  43. }
  44. gl::Error Framebuffer9::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const
  45. {
  46. ASSERT(pack.pixelBuffer.get() == nullptr);
  47. const gl::FramebufferAttachment *colorbuffer = mData.getColorAttachment(0);
  48. ASSERT(colorbuffer);
  49. RenderTarget9 *renderTarget = nullptr;
  50. gl::Error error = colorbuffer->getRenderTarget(&renderTarget);
  51. if (error.isError())
  52. {
  53. return error;
  54. }
  55. ASSERT(renderTarget);
  56. IDirect3DSurface9 *surface = renderTarget->getSurface();
  57. ASSERT(surface);
  58. D3DSURFACE_DESC desc;
  59. surface->GetDesc(&desc);
  60. if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
  61. {
  62. UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
  63. SafeRelease(surface);
  64. return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments.");
  65. }
  66. IDirect3DDevice9 *device = mRenderer->getDevice();
  67. ASSERT(device);
  68. HRESULT result;
  69. IDirect3DSurface9 *systemSurface = nullptr;
  70. bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && mRenderer->getShareHandleSupport() &&
  71. area.x == 0 && area.y == 0 &&
  72. static_cast<UINT>(area.width) == desc.Width && static_cast<UINT>(area.height) == desc.Height &&
  73. desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
  74. if (directToPixels)
  75. {
  76. // Use the pixels ptr as a shared handle to write directly into client's memory
  77. result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
  78. D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast<void**>(&pixels));
  79. if (FAILED(result))
  80. {
  81. // Try again without the shared handle
  82. directToPixels = false;
  83. }
  84. }
  85. if (!directToPixels)
  86. {
  87. result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
  88. D3DPOOL_SYSTEMMEM, &systemSurface, nullptr);
  89. if (FAILED(result))
  90. {
  91. ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
  92. SafeRelease(surface);
  93. return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels.");
  94. }
  95. }
  96. result = device->GetRenderTargetData(surface, systemSurface);
  97. SafeRelease(surface);
  98. if (FAILED(result))
  99. {
  100. SafeRelease(systemSurface);
  101. // It turns out that D3D will sometimes produce more error
  102. // codes than those documented.
  103. if (d3d9::isDeviceLostError(result))
  104. {
  105. mRenderer->notifyDeviceLost();
  106. }
  107. else
  108. {
  109. UNREACHABLE();
  110. }
  111. return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data.");
  112. }
  113. if (directToPixels)
  114. {
  115. SafeRelease(systemSurface);
  116. return gl::Error(GL_NO_ERROR);
  117. }
  118. RECT rect;
  119. rect.left = gl::clamp(area.x, 0L, static_cast<LONG>(desc.Width));
  120. rect.top = gl::clamp(area.y, 0L, static_cast<LONG>(desc.Height));
  121. rect.right = gl::clamp(area.x + area.width, 0L, static_cast<LONG>(desc.Width));
  122. rect.bottom = gl::clamp(area.y + area.height, 0L, static_cast<LONG>(desc.Height));
  123. D3DLOCKED_RECT lock;
  124. result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
  125. if (FAILED(result))
  126. {
  127. UNREACHABLE();
  128. SafeRelease(systemSurface);
  129. return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target.");
  130. }
  131. uint8_t *source;
  132. int inputPitch;
  133. if (pack.reverseRowOrder)
  134. {
  135. source = reinterpret_cast<uint8_t*>(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
  136. inputPitch = -lock.Pitch;
  137. }
  138. else
  139. {
  140. source = reinterpret_cast<uint8_t*>(lock.pBits);
  141. inputPitch = lock.Pitch;
  142. }
  143. const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
  144. const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat);
  145. if (sourceFormatInfo.format == format && sourceFormatInfo.type == type)
  146. {
  147. // Direct copy possible
  148. for (int y = 0; y < rect.bottom - rect.top; y++)
  149. {
  150. memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes);
  151. }
  152. }
  153. else
  154. {
  155. const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
  156. ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type);
  157. GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(format, type);
  158. const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat);
  159. if (fastCopyFunc)
  160. {
  161. // Fast copy is possible through some special function
  162. for (int y = 0; y < rect.bottom - rect.top; y++)
  163. {
  164. for (int x = 0; x < rect.right - rect.left; x++)
  165. {
  166. uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes;
  167. const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
  168. fastCopyFunc(src, dest);
  169. }
  170. }
  171. }
  172. else
  173. {
  174. ColorReadFunction colorReadFunction = sourceD3DFormatInfo.colorReadFunction;
  175. ColorWriteFunction colorWriteFunction = GetColorWriteFunction(format, type);
  176. uint8_t temp[sizeof(gl::ColorF)];
  177. for (int y = 0; y < rect.bottom - rect.top; y++)
  178. {
  179. for (int x = 0; x < rect.right - rect.left; x++)
  180. {
  181. uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes;
  182. const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
  183. // readFunc and writeFunc will be using the same type of color, CopyTexImage
  184. // will not allow the copy otherwise.
  185. colorReadFunction(src, temp);
  186. colorWriteFunction(temp, dest);
  187. }
  188. }
  189. }
  190. }
  191. systemSurface->UnlockRect();
  192. SafeRelease(systemSurface);
  193. return gl::Error(GL_NO_ERROR);
  194. }
  195. gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
  196. bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
  197. const gl::Framebuffer *sourceFramebuffer)
  198. {
  199. ASSERT(filter == GL_NEAREST);
  200. IDirect3DDevice9 *device = mRenderer->getDevice();
  201. ASSERT(device);
  202. mRenderer->endScene();
  203. if (blitRenderTarget)
  204. {
  205. const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorbuffer(0);
  206. ASSERT(readBuffer);
  207. RenderTarget9 *readRenderTarget = nullptr;
  208. gl::Error error = readBuffer->getRenderTarget(&readRenderTarget);
  209. if (error.isError())
  210. {
  211. return error;
  212. }
  213. ASSERT(readRenderTarget);
  214. const gl::FramebufferAttachment *drawBuffer = mData.getColorAttachment(0);
  215. ASSERT(drawBuffer);
  216. RenderTarget9 *drawRenderTarget = nullptr;
  217. error = drawBuffer->getRenderTarget(&drawRenderTarget);
  218. if (error.isError())
  219. {
  220. return error;
  221. }
  222. ASSERT(drawRenderTarget);
  223. // The getSurface calls do an AddRef so save them until after no errors are possible
  224. IDirect3DSurface9* readSurface = readRenderTarget->getSurface();
  225. ASSERT(readSurface);
  226. IDirect3DSurface9* drawSurface = drawRenderTarget->getSurface();
  227. ASSERT(drawSurface);
  228. gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
  229. gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
  230. RECT srcRect;
  231. srcRect.left = sourceArea.x;
  232. srcRect.right = sourceArea.x + sourceArea.width;
  233. srcRect.top = sourceArea.y;
  234. srcRect.bottom = sourceArea.y + sourceArea.height;
  235. RECT dstRect;
  236. dstRect.left = destArea.x;
  237. dstRect.right = destArea.x + destArea.width;
  238. dstRect.top = destArea.y;
  239. dstRect.bottom = destArea.y + destArea.height;
  240. // Clip the rectangles to the scissor rectangle
  241. if (scissor)
  242. {
  243. if (dstRect.left < scissor->x)
  244. {
  245. srcRect.left += (scissor->x - dstRect.left);
  246. dstRect.left = scissor->x;
  247. }
  248. if (dstRect.top < scissor->y)
  249. {
  250. srcRect.top += (scissor->y - dstRect.top);
  251. dstRect.top = scissor->y;
  252. }
  253. if (dstRect.right > scissor->x + scissor->width)
  254. {
  255. srcRect.right -= (dstRect.right - (scissor->x + scissor->width));
  256. dstRect.right = scissor->x + scissor->width;
  257. }
  258. if (dstRect.bottom > scissor->y + scissor->height)
  259. {
  260. srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height));
  261. dstRect.bottom = scissor->y + scissor->height;
  262. }
  263. }
  264. // Clip the rectangles to the destination size
  265. if (dstRect.left < 0)
  266. {
  267. srcRect.left += -dstRect.left;
  268. dstRect.left = 0;
  269. }
  270. if (dstRect.right > dstSize.width)
  271. {
  272. srcRect.right -= (dstRect.right - dstSize.width);
  273. dstRect.right = dstSize.width;
  274. }
  275. if (dstRect.top < 0)
  276. {
  277. srcRect.top += -dstRect.top;
  278. dstRect.top = 0;
  279. }
  280. if (dstRect.bottom > dstSize.height)
  281. {
  282. srcRect.bottom -= (dstRect.bottom - dstSize.height);
  283. dstRect.bottom = dstSize.height;
  284. }
  285. // Clip the rectangles to the source size
  286. if (srcRect.left < 0)
  287. {
  288. dstRect.left += -srcRect.left;
  289. srcRect.left = 0;
  290. }
  291. if (srcRect.right > srcSize.width)
  292. {
  293. dstRect.right -= (srcRect.right - srcSize.width);
  294. srcRect.right = srcSize.width;
  295. }
  296. if (srcRect.top < 0)
  297. {
  298. dstRect.top += -srcRect.top;
  299. srcRect.top = 0;
  300. }
  301. if (srcRect.bottom > srcSize.height)
  302. {
  303. dstRect.bottom -= (srcRect.bottom - srcSize.height);
  304. srcRect.bottom = srcSize.height;
  305. }
  306. HRESULT result = device->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
  307. SafeRelease(readSurface);
  308. SafeRelease(drawSurface);
  309. if (FAILED(result))
  310. {
  311. return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
  312. }
  313. }
  314. if (blitDepth || blitStencil)
  315. {
  316. const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer();
  317. ASSERT(readBuffer);
  318. RenderTarget9 *readDepthStencil = nullptr;
  319. gl::Error error = readBuffer->getRenderTarget(&readDepthStencil);
  320. if (error.isError())
  321. {
  322. return error;
  323. }
  324. ASSERT(readDepthStencil);
  325. const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment();
  326. ASSERT(drawBuffer);
  327. RenderTarget9 *drawDepthStencil = nullptr;
  328. error = drawBuffer->getRenderTarget(&drawDepthStencil);
  329. if (error.isError())
  330. {
  331. return error;
  332. }
  333. ASSERT(drawDepthStencil);
  334. // The getSurface calls do an AddRef so save them until after no errors are possible
  335. IDirect3DSurface9* readSurface = readDepthStencil->getSurface();
  336. ASSERT(readDepthStencil);
  337. IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface();
  338. ASSERT(drawDepthStencil);
  339. HRESULT result = device->StretchRect(readSurface, nullptr, drawSurface, nullptr, D3DTEXF_NONE);
  340. SafeRelease(readSurface);
  341. SafeRelease(drawSurface);
  342. if (FAILED(result))
  343. {
  344. return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
  345. }
  346. }
  347. return gl::Error(GL_NO_ERROR);
  348. }
  349. GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
  350. {
  351. RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTarget);
  352. const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat());
  353. return d3dFormatInfo.internalFormat;
  354. }
  355. }