blob: 66bcc26ff79e55d8ab6cab520b73bc379cccfca7 [file] [log] [blame]
daniel@transgaming.coma8aac672012-12-20 21:08:00 +00001//
2// Copyright (c) 2012 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
7// Image11.h: Implements the rx::Image11 class, which acts as the interface to
8// the actual underlying resources of a Texture
9
10#include "libGLESv2/renderer/Renderer11.h"
11#include "libGLESv2/renderer/Image11.h"
daniel@transgaming.com46cf2492013-01-11 04:06:43 +000012#include "libGLESv2/renderer/TextureStorage11.h"
daniel@transgaming.coma8aac672012-12-20 21:08:00 +000013
14#include "libGLESv2/main.h"
15#include "libGLESv2/mathutil.h"
16#include "libGLESv2/renderer/renderer11_utils.h"
17
18namespace rx
19{
20
21Image11::Image11()
22{
23 mStagingTexture = NULL;
24 mRenderer = NULL;
25 mDXGIFormat = DXGI_FORMAT_UNKNOWN;
26}
27
28Image11::~Image11()
29{
30 if (mStagingTexture)
31 {
32 mStagingTexture->Release();
33 }
34}
35
36Image11 *Image11::makeImage11(Image *img)
37{
38 ASSERT(dynamic_cast<rx::Image11*>(img) != NULL);
39 return static_cast<rx::Image11*>(img);
40}
41
42bool Image11::isDirty() const
43{
44 return (mStagingTexture && mDirty);
45}
46
daniel@transgaming.com5ea16ef2013-01-11 04:06:30 +000047ID3D11Texture2D *Image11::getStagingTexture()
48{
49 createStagingTexture();
50
51 return mStagingTexture;
52}
53
daniel@transgaming.com87705f82012-12-20 21:10:45 +000054bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
daniel@transgaming.coma8aac672012-12-20 21:08:00 +000055{
daniel@transgaming.com46cf2492013-01-11 04:06:43 +000056 TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
57 return storage11->updateSubresourceLevel(getStagingTexture(), level, 0, xoffset, yoffset, width, height);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +000058}
59
daniel@transgaming.com87705f82012-12-20 21:10:45 +000060bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
daniel@transgaming.coma8aac672012-12-20 21:08:00 +000061{
daniel@transgaming.com46cf2492013-01-11 04:06:43 +000062 TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
63 return storage11->updateSubresourceLevel(getStagingTexture(), level, face, xoffset, yoffset, width, height);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +000064}
65
66bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
67{
68 if (mWidth != width ||
69 mHeight != height ||
70 mInternalFormat != internalformat ||
71 forceRelease)
72 {
73 mRenderer = Renderer11::makeRenderer11(renderer);
74
75 mWidth = width;
76 mHeight = height;
77 mInternalFormat = internalformat;
78 // compute the d3d format that will be used
79 mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat);
80 mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat);
81
82 if (mStagingTexture)
83 {
84 mStagingTexture->Release();
85 mStagingTexture = NULL;
86 }
87
88 return true;
89 }
90
91 return false;
92}
93
94bool Image11::isRenderableFormat() const
95{
shannon.woods@transgaming.com2a0a39e2013-01-25 21:50:15 +000096 return TextureStorage11::IsTextureFormatRenderable(mDXGIFormat);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +000097}
98
99DXGI_FORMAT Image11::getDXGIFormat() const
100{
101 // this should only happen if the image hasn't been redefined first
102 // which would be a bug by the caller
103 ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN);
104
105 return mDXGIFormat;
106}
107
108// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
109// into the target pixel rectangle.
110void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
111 GLint unpackAlignment, const void *input)
112{
113 D3D11_MAPPED_SUBRESOURCE mappedImage;
114 HRESULT result = map(&mappedImage);
115 if (FAILED(result))
116 {
117 ERR("Could not map image for loading.");
118 return;
119 }
120
121 GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
122 size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8;
123 void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize));
124
125 switch (mInternalFormat)
126 {
127 case GL_ALPHA8_EXT:
daniel@transgaming.com26041c92013-01-11 04:08:58 +0000128 loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000129 break;
130 case GL_LUMINANCE8_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000131 loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000132 break;
133 case GL_ALPHA32F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000134 loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000135 break;
136 case GL_LUMINANCE32F_EXT:
daniel@transgaming.com26041c92013-01-11 04:08:58 +0000137 loadLuminanceFloatDataToRGB(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000138 break;
139 case GL_ALPHA16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000140 loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000141 break;
142 case GL_LUMINANCE16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000143 loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000144 break;
145 case GL_LUMINANCE8_ALPHA8_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000146 loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000147 break;
148 case GL_LUMINANCE_ALPHA32F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000149 loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000150 break;
151 case GL_LUMINANCE_ALPHA16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000152 loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000153 break;
154 case GL_RGB8_OES:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000155 loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000156 break;
157 case GL_RGB565:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000158 loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000159 break;
160 case GL_RGBA8_OES:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000161 loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000162 break;
163 case GL_RGBA4:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000164 loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000165 break;
166 case GL_RGB5_A1:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000167 loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000168 break;
169 case GL_BGRA8_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000170 loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000171 break;
172 case GL_RGB32F_EXT:
daniel@transgaming.com005979d2012-12-20 21:11:29 +0000173 loadRGBFloatDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000174 break;
175 case GL_RGB16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000176 loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000177 break;
178 case GL_RGBA32F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000179 loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000180 break;
181 case GL_RGBA16F_EXT:
daniel@transgaming.com8ca7d372012-12-20 21:11:22 +0000182 loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
daniel@transgaming.coma8aac672012-12-20 21:08:00 +0000183 break;
184 default: UNREACHABLE();
185 }
186
187 unmap();
188}
189
190void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
191 const void *input)
192{
193 ASSERT(xoffset % 4 == 0);
194 ASSERT(yoffset % 4 == 0);
195
196 D3D11_MAPPED_SUBRESOURCE mappedImage;
197 HRESULT result = map(&mappedImage);
198 if (FAILED(result))
199 {
200 ERR("Could not map image for loading.");
201 return;
202 }
203
204 // Size computation assumes a 4x4 block compressed texture format
205 size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8;
206 void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize));
207
208 GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
209 GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
210 int rows = inputSize / inputPitch;
211 for (int i = 0; i < rows; ++i)
212 {
213 memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
214 }
215
216 unmap();
217}
218
219void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
220{
221 // TODO
222 UNIMPLEMENTED();
223}
224
225void Image11::createStagingTexture()
226{
227 if (mStagingTexture)
228 {
229 return;
230 }
231
232 ID3D11Texture2D *newTexture = NULL;
233 const DXGI_FORMAT dxgiFormat = getDXGIFormat();
234 ASSERT(dxgiFormat != DXGI_FORMAT_D24_UNORM_S8_UINT); // We should never get here for depth textures
235
236 if (mWidth != 0 && mHeight != 0)
237 {
238 ID3D11Device *device = mRenderer->getDevice();
239
240 D3D11_TEXTURE2D_DESC desc;
241 desc.Width = mWidth;
242 desc.Height = mHeight;
243 desc.MipLevels = desc.ArraySize = 1;
244 desc.Format = dxgiFormat;
245 desc.SampleDesc.Count = 1;
246 desc.SampleDesc.Quality = 0;
247 desc.Usage = D3D11_USAGE_STAGING;
248 desc.BindFlags = 0;
249 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
250 desc.MiscFlags = 0;
251
252 HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture);
253
254 if (FAILED(result))
255 {
256 ASSERT(result == E_OUTOFMEMORY);
257 ERR("Creating image failed.");
258 return error(GL_OUT_OF_MEMORY);
259 }
260 }
261
262 mStagingTexture = newTexture;
263 mDirty = false;
264}
265
266HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map)
267{
268 createStagingTexture();
269
270 HRESULT result = D3DERR_INVALIDCALL;
271
272 if (mStagingTexture)
273 {
274 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
275 result = deviceContext->Map(mStagingTexture, 0, D3D11_MAP_WRITE, 0, map);
276 ASSERT(SUCCEEDED(result));
277
278 mDirty = true;
279 }
280
281 return result;
282}
283
284void Image11::unmap()
285{
286 if (mStagingTexture)
287 {
288 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
289 deviceContext->Unmap(mStagingTexture, 0);
290 }
291}
292
293}