Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d / d3d9 / TextureStorage9.cpp
1 //
2 // Copyright (c) 2012-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
7 // TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived
8 // classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
9 // D3D9 texture.
10
11 #include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h"
12 #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
13 #include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h"
14 #include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
15 #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
16 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
17 #include "libGLESv2/renderer/d3d/TextureD3D.h"
18 #include "libGLESv2/Texture.h"
19 #include "libGLESv2/main.h"
20
21 namespace rx
22 {
23 TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage)
24     : mTopLevel(0),
25       mMipLevels(0),
26       mTextureWidth(0),
27       mTextureHeight(0),
28       mTextureFormat(D3DFMT_UNKNOWN),
29       mRenderer(Renderer9::makeRenderer9(renderer)),
30       mD3DUsage(usage),
31       mD3DPool(mRenderer->getTexturePool(usage))
32 {
33 }
34
35 TextureStorage9::~TextureStorage9()
36 {
37 }
38
39 TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage)
40 {
41     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9*, storage));
42     return static_cast<TextureStorage9*>(storage);
43 }
44
45 DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget)
46 {
47     DWORD d3dusage = 0;
48
49     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
50     const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
51     if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
52     {
53         d3dusage |= D3DUSAGE_DEPTHSTENCIL;
54     }
55     else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN))
56     {
57         d3dusage |= D3DUSAGE_RENDERTARGET;
58     }
59
60     return d3dusage;
61 }
62
63
64 bool TextureStorage9::isRenderTarget() const
65 {
66     return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
67 }
68
69 bool TextureStorage9::isManaged() const
70 {
71     return (mD3DPool == D3DPOOL_MANAGED);
72 }
73
74 D3DPOOL TextureStorage9::getPool() const
75 {
76     return mD3DPool;
77 }
78
79 DWORD TextureStorage9::getUsage() const
80 {
81     return mD3DUsage;
82 }
83
84 int TextureStorage9::getTopLevel() const
85 {
86     return mTopLevel;
87 }
88
89 int TextureStorage9::getLevelCount() const
90 {
91     return mMipLevels - mTopLevel;
92 }
93
94 gl::Error TextureStorage9::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
95                                    const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
96 {
97     UNREACHABLE();
98     return gl::Error(GL_INVALID_OPERATION);
99 }
100
101 TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain)
102     : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET)
103 {
104     IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
105     mTexture = surfaceTexture;
106     mMipLevels = surfaceTexture->GetLevelCount();
107
108     D3DSURFACE_DESC surfaceDesc;
109     surfaceTexture->GetLevelDesc(0, &surfaceDesc);
110     mTextureWidth = surfaceDesc.Width;
111     mTextureHeight = surfaceDesc.Height;
112     mTextureFormat = surfaceDesc.Format;
113
114     mRenderTarget = NULL;
115
116     initializeSerials(1, 1);
117 }
118
119 TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
120     : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
121 {
122     mTexture = NULL;
123     mRenderTarget = NULL;
124
125     const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
126     mTextureFormat = d3dFormatInfo.texFormat;
127
128     d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel);
129     mTextureWidth = width;
130     mTextureHeight = height;
131     mMipLevels = mTopLevel + levels;
132
133     initializeSerials(getLevelCount(), 1);
134 }
135
136 TextureStorage9_2D::~TextureStorage9_2D()
137 {
138     SafeRelease(mTexture);
139     SafeDelete(mRenderTarget);
140 }
141
142 TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage)
143 {
144     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_2D*, storage));
145     return static_cast<TextureStorage9_2D*>(storage);
146 }
147
148 // Increments refcount on surface.
149 // caller must Release() the returned surface
150 gl::Error TextureStorage9_2D::getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface)
151 {
152     IDirect3DBaseTexture9 *baseTexture = NULL;
153     gl::Error error = getBaseTexture(&baseTexture);
154     if (error.isError())
155     {
156         return error;
157     }
158
159     IDirect3DTexture9 *texture = static_cast<IDirect3DTexture9*>(baseTexture);
160
161     HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface);
162
163     ASSERT(SUCCEEDED(result));
164     if (FAILED(result))
165     {
166         return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
167     }
168
169     // With managed textures the driver needs to be informed of updates to the lower mipmap levels
170     if (level + mTopLevel != 0 && isManaged() && dirty)
171     {
172         texture->AddDirtyRect(NULL);
173     }
174
175     return gl::Error(GL_NO_ERROR);
176 }
177
178 gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTarget **outRT)
179 {
180     if (!mRenderTarget && isRenderTarget())
181     {
182         IDirect3DSurface9 *surface = NULL;
183         gl::Error error = getSurfaceLevel(0, false, &surface);
184         if (error.isError())
185         {
186             return error;
187         }
188
189         mRenderTarget = new RenderTarget9(mRenderer, surface);
190     }
191
192     ASSERT(outRT);
193     *outRT = mRenderTarget;
194     return gl::Error(GL_NO_ERROR);
195 }
196
197 gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
198 {
199     IDirect3DSurface9 *upper = NULL;
200     gl::Error error = getSurfaceLevel(sourceIndex.mipIndex, false, &upper);
201     if (error.isError())
202     {
203         return error;
204     }
205
206     IDirect3DSurface9 *lower = NULL;
207     error = getSurfaceLevel(destIndex.mipIndex, true, &lower);
208     if (error.isError())
209     {
210         SafeRelease(upper);
211         return error;
212     }
213
214     ASSERT(upper && lower);
215     error = mRenderer->boxFilter(upper, lower);
216
217     SafeRelease(upper);
218     SafeRelease(lower);
219
220     return error;
221 }
222
223 gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
224 {
225     // if the width or height is not positive this should be treated as an incomplete texture
226     // we handle that here by skipping the d3d texture creation
227     if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
228     {
229         ASSERT(mMipLevels > 0);
230
231         IDirect3DDevice9 *device = mRenderer->getDevice();
232         HRESULT result = device->CreateTexture(mTextureWidth, mTextureHeight, mMipLevels, getUsage(), mTextureFormat,
233                                                getPool(), &mTexture, NULL);
234
235         if (FAILED(result))
236         {
237             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
238             return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D storage texture, result: 0x%X.", result);
239         }
240     }
241
242     *outTexture = mTexture;
243     return gl::Error(GL_NO_ERROR);
244 }
245
246 gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
247 {
248     ASSERT(destStorage);
249
250     TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(destStorage);
251
252     int levels = getLevelCount();
253     for (int i = 0; i < levels; ++i)
254     {
255         IDirect3DSurface9 *srcSurf = NULL;
256         gl::Error error = getSurfaceLevel(i, false, &srcSurf);
257         if (error.isError())
258         {
259             return error;
260         }
261
262         IDirect3DSurface9 *dstSurf = NULL;
263         error = dest9->getSurfaceLevel(i, true, &dstSurf);
264         if (error.isError())
265         {
266             SafeRelease(srcSurf);
267             return error;
268         }
269
270         error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
271
272         SafeRelease(srcSurf);
273         SafeRelease(dstSurf);
274
275         if (error.isError())
276         {
277             return error;
278         }
279     }
280
281     return gl::Error(GL_NO_ERROR);
282 }
283
284 TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
285     : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
286 {
287     mTexture = NULL;
288     for (int i = 0; i < CUBE_FACE_COUNT; ++i)
289     {
290         mRenderTarget[i] = NULL;
291     }
292
293     const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
294     mTextureFormat = d3dFormatInfo.texFormat;
295
296     int height = size;
297     d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel);
298     mTextureWidth = size;
299     mTextureHeight = size;
300     mMipLevels = mTopLevel + levels;
301
302     initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT);
303 }
304
305 TextureStorage9_Cube::~TextureStorage9_Cube()
306 {
307     SafeRelease(mTexture);
308
309     for (int i = 0; i < CUBE_FACE_COUNT; ++i)
310     {
311         SafeDelete(mRenderTarget[i]);
312     }
313 }
314
315 TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStorage *storage)
316 {
317     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_Cube*, storage));
318     return static_cast<TextureStorage9_Cube*>(storage);
319 }
320
321 // Increments refcount on surface.
322 // caller must Release() the returned surface
323 gl::Error TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface)
324 {
325     IDirect3DBaseTexture9 *baseTexture = NULL;
326     gl::Error error = getBaseTexture(&baseTexture);
327     if (error.isError())
328     {
329         return error;
330     }
331
332     IDirect3DCubeTexture9 *texture = static_cast<IDirect3DCubeTexture9*>(baseTexture);
333
334     D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget);
335     HRESULT result = texture->GetCubeMapSurface(face, level + mTopLevel, outSurface);
336
337     ASSERT(SUCCEEDED(result));
338     if (FAILED(result))
339     {
340         return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
341     }
342
343     // With managed textures the driver needs to be informed of updates to the lower mipmap levels
344     if (level != 0 && isManaged() && dirty)
345     {
346         texture->AddDirtyRect(face, NULL);
347     }
348
349     return gl::Error(GL_NO_ERROR);
350 }
351
352 gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
353 {
354     ASSERT(outRT);
355     ASSERT(index.mipIndex == 0);
356     ASSERT(index.layerIndex >= 0 && index.layerIndex < CUBE_FACE_COUNT);
357
358     if (mRenderTarget[index.layerIndex] == NULL && isRenderTarget())
359     {
360         IDirect3DSurface9 *surface = NULL;
361         gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex, 0, false, &surface);
362         if (error.isError())
363         {
364             return error;
365         }
366
367         mRenderTarget[index.layerIndex] = new RenderTarget9(mRenderer, surface);
368     }
369
370     *outRT = mRenderTarget[index.layerIndex];
371     return gl::Error(GL_NO_ERROR);
372 }
373
374 gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
375 {
376     IDirect3DSurface9 *upper = NULL;
377     gl::Error error = getCubeMapSurface(sourceIndex.type, sourceIndex.mipIndex, false, &upper);
378     if (error.isError())
379     {
380         return error;
381     }
382
383     IDirect3DSurface9 *lower = NULL;
384     error = getCubeMapSurface(destIndex.type, destIndex.mipIndex, true, &lower);
385     if (error.isError())
386     {
387         SafeRelease(upper);
388         return error;
389     }
390
391     ASSERT(upper && lower);
392     error = mRenderer->boxFilter(upper, lower);
393
394     SafeRelease(upper);
395     SafeRelease(lower);
396
397     return error;
398 }
399
400 gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
401 {
402     // if the size is not positive this should be treated as an incomplete texture
403     // we handle that here by skipping the d3d texture creation
404     if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
405     {
406         ASSERT(mMipLevels > 0);
407         ASSERT(mTextureWidth == mTextureHeight);
408
409         IDirect3DDevice9 *device = mRenderer->getDevice();
410         HRESULT result = device->CreateCubeTexture(mTextureWidth, mMipLevels, getUsage(), mTextureFormat, getPool(),
411                                                    &mTexture, NULL);
412
413         if (FAILED(result))
414         {
415             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
416             return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result);
417         }
418     }
419
420     *outTexture = mTexture;
421     return gl::Error(GL_NO_ERROR);
422 }
423
424 gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage)
425 {
426     ASSERT(destStorage);
427
428     TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(destStorage);
429
430     int levels = getLevelCount();
431     for (int f = 0; f < CUBE_FACE_COUNT; f++)
432     {
433         for (int i = 0; i < levels; i++)
434         {
435             IDirect3DSurface9 *srcSurf = NULL;
436             gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf);
437             if (error.isError())
438             {
439                 return error;
440             }
441
442             IDirect3DSurface9 *dstSurf = NULL;
443             error = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf);
444             if (error.isError())
445             {
446                 SafeRelease(srcSurf);
447                 return error;
448             }
449
450             error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
451
452             SafeRelease(srcSurf);
453             SafeRelease(dstSurf);
454
455             if (error.isError())
456             {
457                 return error;
458             }
459         }
460     }
461
462     return gl::Error(GL_NO_ERROR);
463 }
464
465 }