blob: d359164990452e8042f0f8820c3b586b8ed5a265 [file] [log] [blame]
Brandon Jonesf47bebc2014-07-09 14:28:42 -07001//
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
7// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends.
8
Geoff Lang0b7eef72014-06-12 14:10:47 -04009#include "libGLESv2/renderer/d3d/TextureD3D.h"
10#include "libGLESv2/renderer/d3d/TextureStorage.h"
11#include "libGLESv2/renderer/d3d/ImageD3D.h"
Brandon Jonesf47bebc2014-07-09 14:28:42 -070012#include "libGLESv2/Buffer.h"
13#include "libGLESv2/Framebuffer.h"
Brandon Jonescef06ff2014-08-05 13:27:48 -070014#include "libGLESv2/Texture.h"
Brandon Jonesf47bebc2014-07-09 14:28:42 -070015#include "libGLESv2/main.h"
16#include "libGLESv2/formatutils.h"
17#include "libGLESv2/renderer/BufferImpl.h"
18#include "libGLESv2/renderer/RenderTarget.h"
19#include "libGLESv2/renderer/Renderer.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040020
21#include "libEGL/Surface.h"
22
23#include "common/mathutil.h"
24#include "common/utilities.h"
Brandon Jonesf47bebc2014-07-09 14:28:42 -070025
26namespace rx
27{
28
Brandon Jonesf47bebc2014-07-09 14:28:42 -070029bool IsRenderTargetUsage(GLenum usage)
30{
31 return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
32}
33
Brandon Jones78b1acd2014-07-15 15:33:07 -070034TextureD3D::TextureD3D(Renderer *renderer)
Brandon Jonesf47bebc2014-07-09 14:28:42 -070035 : mRenderer(renderer),
36 mUsage(GL_NONE),
37 mDirtyImages(true),
Jamie Madill98553e32014-09-30 16:33:50 -040038 mImmutable(false),
39 mTexStorage(NULL)
Brandon Jonesf47bebc2014-07-09 14:28:42 -070040{
41}
42
43TextureD3D::~TextureD3D()
44{
45}
46
Brandon Jones6053a522014-07-25 16:22:09 -070047TextureD3D *TextureD3D::makeTextureD3D(TextureImpl *texture)
48{
49 ASSERT(HAS_DYNAMIC_TYPE(TextureD3D*, texture));
50 return static_cast<TextureD3D*>(texture);
51}
52
Jamie Madill2f06dbf2014-09-18 15:08:50 -040053TextureStorage *TextureD3D::getNativeTexture()
Brandon Jones6053a522014-07-25 16:22:09 -070054{
55 // ensure the underlying texture is created
56 initializeStorage(false);
57
Jamie Madill98553e32014-09-30 16:33:50 -040058 if (mTexStorage)
Brandon Jones6053a522014-07-25 16:22:09 -070059 {
60 updateStorage();
61 }
62
Jamie Madill98553e32014-09-30 16:33:50 -040063 return mTexStorage;
Brandon Jones6053a522014-07-25 16:22:09 -070064}
65
Brandon Jonesf47bebc2014-07-09 14:28:42 -070066GLint TextureD3D::getBaseLevelWidth() const
67{
Brandon Jones78b1acd2014-07-15 15:33:07 -070068 const Image *baseImage = getBaseLevelImage();
Brandon Jonesf47bebc2014-07-09 14:28:42 -070069 return (baseImage ? baseImage->getWidth() : 0);
70}
71
72GLint TextureD3D::getBaseLevelHeight() const
73{
Brandon Jones78b1acd2014-07-15 15:33:07 -070074 const Image *baseImage = getBaseLevelImage();
Brandon Jonesf47bebc2014-07-09 14:28:42 -070075 return (baseImage ? baseImage->getHeight() : 0);
76}
77
78GLint TextureD3D::getBaseLevelDepth() const
79{
Brandon Jones78b1acd2014-07-15 15:33:07 -070080 const Image *baseImage = getBaseLevelImage();
Brandon Jonesf47bebc2014-07-09 14:28:42 -070081 return (baseImage ? baseImage->getDepth() : 0);
82}
83
84// Note: "base level image" is loosely defined to be any image from the base level,
85// where in the base of 2D array textures and cube maps there are several. Don't use
86// the base level image for anything except querying texture format and size.
87GLenum TextureD3D::getBaseLevelInternalFormat() const
88{
Brandon Jones78b1acd2014-07-15 15:33:07 -070089 const Image *baseImage = getBaseLevelImage();
Brandon Jonesf47bebc2014-07-09 14:28:42 -070090 return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
91}
92
Jamie Madillba6bc952014-10-06 10:56:22 -040093gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, const gl::ImageIndex &index)
Brandon Jonesf47bebc2014-07-09 14:28:42 -070094{
Jamie Madillba6bc952014-10-06 10:56:22 -040095 Image *image = getImage(index);
96
Brandon Jonesf47bebc2014-07-09 14:28:42 -070097 // No-op
98 if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
99 {
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400100 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700101 }
102
103 // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
104 // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
Jamie Madill9aca0592014-10-06 16:26:59 -0400105 const uint8_t *pixelData = NULL;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700106
107 if (unpack.pixelBuffer.id() != 0)
108 {
109 // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported
110 gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
111 ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
112 // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data.
113 // This functionality should be moved into renderer and the getData method of BufferImpl removed.
114 const void *bufferData = pixelBuffer->getImplementation()->getData();
Jamie Madill9aca0592014-10-06 16:26:59 -0400115 pixelData = static_cast<const uint8_t *>(bufferData) + offset;
116 }
117 else
118 {
119 pixelData = static_cast<const uint8_t *>(pixels);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700120 }
121
122 if (pixelData != NULL)
123 {
Jamie Madill9aca0592014-10-06 16:26:59 -0400124 gl::Error error(GL_NO_ERROR);
125
126 gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(image->getInternalFormat());
127
128 // TODO(jmadill): Handle compressed internal formats
129 if (mTexStorage && mRenderer->getWorkarounds().setDataFasterThanImageUpload && !internalFormat.compressed)
130 {
131 gl::Box sourceBox(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
132 error = mTexStorage->setData(index, sourceBox, image->getInternalFormat(), type, unpack, pixelData);
133 }
134 else
135 {
136 error = image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData);
137 }
138
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400139 if (error.isError())
140 {
141 return error;
142 }
143
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700144 mDirtyImages = true;
145 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400146
147 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700148}
149
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400150gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
151 GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700152{
Jamie Madill9aca0592014-10-06 16:26:59 -0400153 const uint8_t *pixelData = static_cast<const uint8_t *>(pixels);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700154
155 // CPU readback & copy where direct GPU copy is not supported
156 if (unpack.pixelBuffer.id() != 0)
157 {
158 gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
Jacek Cabana5521de2014-10-01 17:23:46 +0200159 uintptr_t offset = reinterpret_cast<uintptr_t>(pixels);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700160 // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data.
161 // This functionality should be moved into renderer and the getData method of BufferImpl removed.
162 const void *bufferData = pixelBuffer->getImplementation()->getData();
Jamie Madill9aca0592014-10-06 16:26:59 -0400163 pixelData = static_cast<const uint8_t *>(bufferData)+offset;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700164 }
165
166 if (pixelData != NULL)
167 {
Jamie Madillfeda4d22014-09-17 13:03:29 -0400168 Image *image = getImage(index);
169 ASSERT(image);
170
Jamie Madill9aca0592014-10-06 16:26:59 -0400171 gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(image->getInternalFormat());
172 gl::Box region(xoffset, yoffset, zoffset, width, height, depth);
173
174 // TODO(jmadill): Handle compressed internal formats
175 if (mTexStorage && mRenderer->getWorkarounds().setDataFasterThanImageUpload && !internalFormat.compressed)
176 {
177 return mTexStorage->setData(index, region, image->getInternalFormat(),
178 type, unpack, pixelData);
179 }
180
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400181 gl::Error error = image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment,
182 type, pixelData);
183 if (error.isError())
184 {
185 return error;
186 }
187
Jamie Madille6b6da02014-10-02 11:03:14 -0400188 error = commitRegion(index, region);
189 if (error.isError())
190 {
191 return error;
192 }
193
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700194 mDirtyImages = true;
195 }
196
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400197 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700198}
199
Geoff Langb5348332014-09-02 13:16:34 -0400200gl::Error TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700201{
202 if (pixels != NULL)
203 {
Geoff Langb5348332014-09-02 13:16:34 -0400204 gl::Error error = image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels);
205 if (error.isError())
206 {
207 return error;
208 }
209
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700210 mDirtyImages = true;
211 }
Geoff Langb5348332014-09-02 13:16:34 -0400212
213 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700214}
215
Geoff Langb5348332014-09-02 13:16:34 -0400216gl::Error TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
Brandon Jones78b1acd2014-07-15 15:33:07 -0700217 GLenum format, GLsizei imageSize, const void *pixels, Image *image)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700218{
219 if (pixels != NULL)
220 {
Geoff Langb5348332014-09-02 13:16:34 -0400221 gl::Error error = image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels);
222 if (error.isError())
223 {
224 return error;
225 }
226
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700227 mDirtyImages = true;
228 }
229
Geoff Langb5348332014-09-02 13:16:34 -0400230 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700231}
232
233bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat)
234{
235 return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
236}
237
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400238gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
239 GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700240{
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400241 // No-op
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700242 if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
243 {
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400244 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700245 }
246
247 // In order to perform the fast copy through the shader, we must have the right format, and be able
248 // to create a render target.
249 ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat));
250
Jacek Cabana5521de2014-10-01 17:23:46 +0200251 uintptr_t offset = reinterpret_cast<uintptr_t>(pixels);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700252
Geoff Langae5122c2014-08-27 14:08:43 -0400253 gl::Error error = mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
254 if (error.isError())
255 {
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400256 return error;
Geoff Langae5122c2014-08-27 14:08:43 -0400257 }
258
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400259 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700260}
261
262GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
263{
264 if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT)
265 {
266 // Maximum number of levels
267 return gl::log2(std::max(std::max(width, height), depth)) + 1;
268 }
269 else
270 {
271 // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
272 return 1;
273 }
274}
275
276int TextureD3D::mipLevels() const
277{
278 return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
279}
280
Jamie Madill98553e32014-09-30 16:33:50 -0400281TextureStorage *TextureD3D::getStorage()
282{
283 return mTexStorage;
284}
285
Jamie Madill3269bcb2014-09-30 16:33:52 -0400286Image *TextureD3D::getBaseLevelImage() const
287{
288 return getImage(getImageIndex(0, 0));
289}
290
Jamie Madill4aa79e12014-09-29 10:46:14 -0400291void TextureD3D::generateMipmaps()
292{
Jamie Madill9aca0592014-10-06 16:26:59 -0400293 GLint mipCount = mipLevels();
294
295 if (mipCount == 1)
296 {
297 return; // no-op
298 }
299
300 // Set up proper mipmap chain in our Image array.
Jamie Madill4aa79e12014-09-29 10:46:14 -0400301 initMipmapsImages();
302
303 // We know that all layers have the same dimension, for the texture to be complete
304 GLint layerCount = static_cast<GLint>(getLayerCount(0));
Jamie Madill4aa79e12014-09-29 10:46:14 -0400305
Jamie Madill9aca0592014-10-06 16:26:59 -0400306 // When making mipmaps with the setData workaround enabled, the texture storage has
307 // the image data already. For non-render-target storage, we have to pull it out into
308 // an image layer.
309 if (mRenderer->getWorkarounds().setDataFasterThanImageUpload && mTexStorage)
310 {
311 if (!mTexStorage->isRenderTarget())
312 {
313 // Copy from the storage mip 0 to Image mip 0
314 for (GLint layer = 0; layer < layerCount; ++layer)
315 {
316 gl::ImageIndex srcIndex = getImageIndex(0, layer);
Jamie Madill4aa79e12014-09-29 10:46:14 -0400317
Jamie Madill9aca0592014-10-06 16:26:59 -0400318 Image *image = getImage(srcIndex);
319 gl::Rectangle area(0, 0, image->getWidth(), image->getHeight());
320 image->copy(0, 0, 0, area, srcIndex, mTexStorage);
321 }
322 }
323 else
324 {
325 updateStorage();
326 }
327 }
328
329 bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget());
Jamie Madill4aa79e12014-09-29 10:46:14 -0400330
331 for (GLint layer = 0; layer < layerCount; ++layer)
332 {
333 for (GLint mip = 1; mip < mipCount; ++mip)
334 {
335 ASSERT(getLayerCount(mip) == layerCount);
336
337 gl::ImageIndex sourceIndex = getImageIndex(mip - 1, layer);
338 gl::ImageIndex destIndex = getImageIndex(mip, layer);
339
340 if (renderableStorage)
341 {
342 // GPU-side mipmapping
Jamie Madill9aca0592014-10-06 16:26:59 -0400343 mTexStorage->generateMipmap(sourceIndex, destIndex);
Jamie Madill4aa79e12014-09-29 10:46:14 -0400344 }
345 else
346 {
347 // CPU-side mipmapping
348 mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex));
349 }
350 }
351 }
352}
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700353
Jamie Madill135570a2014-09-30 16:33:51 -0400354bool TextureD3D::isBaseImageZeroSize() const
355{
Jamie Madill3269bcb2014-09-30 16:33:52 -0400356 Image *baseImage = getBaseLevelImage();
Jamie Madill135570a2014-09-30 16:33:51 -0400357
358 if (!baseImage || baseImage->getWidth() <= 0)
359 {
360 return true;
361 }
362
363 if (!gl::IsCubemapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0)
364 {
365 return true;
366 }
367
368 if (baseImage->getTarget() == GL_TEXTURE_3D && baseImage->getDepth() <= 0)
369 {
370 return true;
371 }
372
373 if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(0) <= 0)
374 {
375 return true;
376 }
377
378 return false;
379}
380
Geoff Langef7b0162014-09-04 13:29:23 -0400381gl::Error TextureD3D::ensureRenderTarget()
Jamie Madill135570a2014-09-30 16:33:51 -0400382{
Geoff Langef7b0162014-09-04 13:29:23 -0400383 gl::Error error = initializeStorage(true);
384 if (error.isError())
385 {
386 return error;
387 }
Jamie Madill135570a2014-09-30 16:33:51 -0400388
389 if (!isBaseImageZeroSize())
390 {
391 ASSERT(mTexStorage);
392 if (!mTexStorage->isRenderTarget())
393 {
Geoff Langef7b0162014-09-04 13:29:23 -0400394 TextureStorage *newRenderTargetStorage = NULL;
395 error = createCompleteStorage(true, &newRenderTargetStorage);
396 if (error.isError())
Jamie Madill135570a2014-09-30 16:33:51 -0400397 {
Geoff Langef7b0162014-09-04 13:29:23 -0400398 return error;
Jamie Madill135570a2014-09-30 16:33:51 -0400399 }
400
Geoff Langef7b0162014-09-04 13:29:23 -0400401 error = mTexStorage->copyToStorage(newRenderTargetStorage);
402 if (error.isError())
403 {
404 SafeDelete(newRenderTargetStorage);
405 return error;
406 }
407
408 error = setCompleteTexStorage(newRenderTargetStorage);
409 if (error.isError())
410 {
411 SafeDelete(newRenderTargetStorage);
412 return error;
413 }
Jamie Madill135570a2014-09-30 16:33:51 -0400414 }
415 }
416
Geoff Langef7b0162014-09-04 13:29:23 -0400417 return gl::Error(GL_NO_ERROR);
Jamie Madill135570a2014-09-30 16:33:51 -0400418}
419
Brandon Jones78b1acd2014-07-15 15:33:07 -0700420TextureD3D_2D::TextureD3D_2D(Renderer *renderer)
Jamie Madill98553e32014-09-30 16:33:50 -0400421 : TextureD3D(renderer)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700422{
423 for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
424 {
425 mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage());
426 }
427}
428
429TextureD3D_2D::~TextureD3D_2D()
430{
Austin Kinross69822602014-08-12 15:51:37 -0700431 // Delete the Images before the TextureStorage.
432 // Images might be relying on the TextureStorage for some of their data.
433 // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700434 for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
435 {
436 delete mImageArray[i];
437 }
Austin Kinross69822602014-08-12 15:51:37 -0700438
439 SafeDelete(mTexStorage);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700440}
441
Brandon Jonescef06ff2014-08-05 13:27:48 -0700442Image *TextureD3D_2D::getImage(int level, int layer) const
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700443{
444 ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
Brandon Jonescef06ff2014-08-05 13:27:48 -0700445 ASSERT(layer == 0);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700446 return mImageArray[level];
447}
448
Jamie Madillfeda4d22014-09-17 13:03:29 -0400449Image *TextureD3D_2D::getImage(const gl::ImageIndex &index) const
450{
451 ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
Jamie Madillac7579c2014-09-17 16:59:33 -0400452 ASSERT(!index.hasLayer());
Jamie Madillfeda4d22014-09-17 13:03:29 -0400453 ASSERT(index.type == GL_TEXTURE_2D);
454 return mImageArray[index.mipIndex];
455}
456
Brandon Jonescef06ff2014-08-05 13:27:48 -0700457GLsizei TextureD3D_2D::getLayerCount(int level) const
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700458{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700459 ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
460 return 1;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700461}
462
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700463GLsizei TextureD3D_2D::getWidth(GLint level) const
464{
465 if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
466 return mImageArray[level]->getWidth();
467 else
468 return 0;
469}
470
471GLsizei TextureD3D_2D::getHeight(GLint level) const
472{
473 if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
474 return mImageArray[level]->getHeight();
475 else
476 return 0;
477}
478
479GLenum TextureD3D_2D::getInternalFormat(GLint level) const
480{
481 if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
482 return mImageArray[level]->getInternalFormat();
483 else
484 return GL_NONE;
485}
486
487GLenum TextureD3D_2D::getActualFormat(GLint level) const
488{
489 if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
490 return mImageArray[level]->getActualFormat();
491 else
492 return GL_NONE;
493}
494
495bool TextureD3D_2D::isDepth(GLint level) const
496{
Geoff Lang5d601382014-07-22 15:14:06 -0400497 return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700498}
499
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400500gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
501 GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
502 const void *pixels)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700503{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700504 ASSERT(target == GL_TEXTURE_2D && depth == 1);
505
Geoff Lang5d601382014-07-22 15:14:06 -0400506 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
507
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700508 bool fastUnpacked = false;
509
Brandon Jonescef06ff2014-08-05 13:27:48 -0700510 redefineImage(level, sizedInternalFormat, width, height);
511
Jamie Madillba6bc952014-10-06 10:56:22 -0400512 gl::ImageIndex index = gl::ImageIndex::Make2D(level);
513
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700514 // Attempt a fast gpu copy of the pixel data to the surface
515 if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level))
516 {
517 // Will try to create RT storage if it does not exist
Jamie Madillac7579c2014-09-17 16:59:33 -0400518 RenderTarget *destRenderTarget = getRenderTarget(index);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700519 gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
520
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400521 if (destRenderTarget)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700522 {
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400523 gl::Error error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget);
524 if (error.isError())
525 {
526 return error;
527 }
528
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700529 // Ensure we don't overwrite our newly initialized data
530 mImageArray[level]->markClean();
531
532 fastUnpacked = true;
533 }
534 }
535
536 if (!fastUnpacked)
537 {
Jamie Madillba6bc952014-10-06 10:56:22 -0400538 gl::Error error = TextureD3D::setImage(unpack, type, pixels, index);
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400539 if (error.isError())
540 {
541 return error;
542 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700543 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400544
545 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700546}
547
Geoff Langb5348332014-09-02 13:16:34 -0400548gl::Error TextureD3D_2D::setCompressedImage(GLenum target, GLint level, GLenum format,
549 GLsizei width, GLsizei height, GLsizei depth,
550 GLsizei imageSize, const void *pixels)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700551{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700552 ASSERT(target == GL_TEXTURE_2D && depth == 1);
553
554 // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
555 redefineImage(level, format, width, height);
556
Geoff Langb5348332014-09-02 13:16:34 -0400557 return TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700558}
559
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400560gl::Error TextureD3D_2D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
561 GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
562 const gl::PixelUnpackState &unpack, const void *pixels)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700563{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700564 ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0);
565
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700566 bool fastUnpacked = false;
567
Jamie Madillac7579c2014-09-17 16:59:33 -0400568 gl::ImageIndex index = gl::ImageIndex::Make2D(level);
Jamie Madill7cb2b9d2014-10-02 11:03:13 -0400569 gl::Box destArea(xoffset, yoffset, 0, width, height, 1);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700570 if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
571 {
Jamie Madillac7579c2014-09-17 16:59:33 -0400572 RenderTarget *renderTarget = getRenderTarget(index);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700573
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400574 if (renderTarget)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700575 {
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400576 gl::Error error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget);
577 if (error.isError())
578 {
579 return error;
580 }
581
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700582 // Ensure we don't overwrite our newly initialized data
583 mImageArray[level]->markClean();
584
585 fastUnpacked = true;
586 }
587 }
588
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400589 if (!fastUnpacked)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700590 {
Jamie Madille6b6da02014-10-02 11:03:14 -0400591 return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type,
592 unpack, pixels, index);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700593 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -0400594
595 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700596}
597
Geoff Langb5348332014-09-02 13:16:34 -0400598gl::Error TextureD3D_2D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
599 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
600 GLsizei imageSize, const void *pixels)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700601{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700602 ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0);
603
Geoff Langb5348332014-09-02 13:16:34 -0400604 gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[level]);
605 if (error.isError())
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700606 {
Geoff Langb5348332014-09-02 13:16:34 -0400607 return error;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700608 }
Geoff Langb5348332014-09-02 13:16:34 -0400609
Jamie Madill7cb2b9d2014-10-02 11:03:13 -0400610 gl::ImageIndex index = gl::ImageIndex::Make2D(level);
611 gl::Box region(xoffset, yoffset, 0, width, height, 1);
612 return commitRegion(index, region);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700613}
614
Geoff Langef7b0162014-09-04 13:29:23 -0400615gl::Error TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height,
616 gl::Framebuffer *source)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700617{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700618 ASSERT(target == GL_TEXTURE_2D);
619
620 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
621 redefineImage(level, sizedInternalFormat, width, height);
622
Jamie Madill82bf0c52014-10-03 11:50:53 -0400623 gl::Rectangle sourceRect(x, y, width, height);
624
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700625 if (!mImageArray[level]->isRenderableFormat())
626 {
Geoff Langef7b0162014-09-04 13:29:23 -0400627 gl::Error error = mImageArray[level]->copy(0, 0, 0, sourceRect, source);
628 if (error.isError())
629 {
630 return error;
631 }
632
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700633 mDirtyImages = true;
634 }
635 else
636 {
Geoff Langef7b0162014-09-04 13:29:23 -0400637 gl::Error error = ensureRenderTarget();
638 if (error.isError())
639 {
640 return error;
641 }
642
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700643 mImageArray[level]->markClean();
644
645 if (width != 0 && height != 0 && isValidLevel(level))
646 {
Geoff Langef7b0162014-09-04 13:29:23 -0400647 gl::Error error = mRenderer->copyImage2D(source, sourceRect, format, 0, 0, mTexStorage, level);
648 if (error.isError())
649 {
650 return error;
651 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700652 }
653 }
Geoff Langef7b0162014-09-04 13:29:23 -0400654
655 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700656}
657
Geoff Langef7b0162014-09-04 13:29:23 -0400658gl::Error TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
659 GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700660{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700661 ASSERT(target == GL_TEXTURE_2D && zoffset == 0);
662
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700663 // can only make our texture storage to a render target if level 0 is defined (with a width & height) and
664 // the current level we're copying to is defined (with appropriate format, width & height)
665 bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
666
Jamie Madill82bf0c52014-10-03 11:50:53 -0400667 gl::Rectangle sourceRect(x, y, width, height);
668
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700669 if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
670 {
Geoff Langef7b0162014-09-04 13:29:23 -0400671 gl::Error error = mImageArray[level]->copy(xoffset, yoffset, 0, sourceRect, source);
672 if (error.isError())
673 {
674 return error;
675 }
676
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700677 mDirtyImages = true;
678 }
679 else
680 {
Geoff Langef7b0162014-09-04 13:29:23 -0400681 gl::Error error = ensureRenderTarget();
682 if (error.isError())
683 {
684 return error;
685 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700686
687 if (isValidLevel(level))
688 {
Geoff Langef7b0162014-09-04 13:29:23 -0400689 error = updateStorageLevel(level);
690 if (error.isError())
691 {
692 return error;
693 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700694
Geoff Langef7b0162014-09-04 13:29:23 -0400695 error = mRenderer->copyImage2D(source, sourceRect,
696 gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
697 xoffset, yoffset, mTexStorage, level);
698 if (error.isError())
699 {
700 return error;
701 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700702 }
703 }
Geoff Langef7b0162014-09-04 13:29:23 -0400704
705 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700706}
707
Brandon Jonescef06ff2014-08-05 13:27:48 -0700708void TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700709{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700710 ASSERT(target == GL_TEXTURE_2D && depth == 1);
711
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700712 for (int level = 0; level < levels; level++)
713 {
714 GLsizei levelWidth = std::max(1, width >> level);
715 GLsizei levelHeight = std::max(1, height >> level);
716 mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, levelWidth, levelHeight, 1, true);
717 }
718
719 for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
720 {
721 mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
722 }
723
724 mImmutable = true;
725
Jamie Madillc4833262014-09-18 16:18:26 -0400726 bool renderTarget = IsRenderTargetUsage(mUsage);
727 TextureStorage *storage = mRenderer->createTextureStorage2D(internalformat, renderTarget, width, height, levels);
Jamie Madill2f06dbf2014-09-18 15:08:50 -0400728 setCompleteTexStorage(storage);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700729}
730
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700731void TextureD3D_2D::bindTexImage(egl::Surface *surface)
732{
733 GLenum internalformat = surface->getFormat();
734
735 mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true);
736
737 if (mTexStorage)
738 {
739 SafeDelete(mTexStorage);
740 }
Jamie Madill2f06dbf2014-09-18 15:08:50 -0400741
742 mTexStorage = mRenderer->createTextureStorage2D(surface->getSwapChain());
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700743
744 mDirtyImages = true;
745}
746
747void TextureD3D_2D::releaseTexImage()
748{
749 if (mTexStorage)
750 {
751 SafeDelete(mTexStorage);
752 }
753
754 for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
755 {
756 mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
757 }
758}
759
Jamie Madill4aa79e12014-09-29 10:46:14 -0400760void TextureD3D_2D::initMipmapsImages()
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700761{
Brandon Jonescef06ff2014-08-05 13:27:48 -0700762 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700763 int levelCount = mipLevels();
Brandon Jonescef06ff2014-08-05 13:27:48 -0700764 for (int level = 1; level < levelCount; level++)
765 {
766 redefineImage(level, getBaseLevelInternalFormat(),
767 std::max(getBaseLevelWidth() >> level, 1),
768 std::max(getBaseLevelHeight() >> level, 1));
769 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700770}
771
Jamie Madillac7579c2014-09-17 16:59:33 -0400772unsigned int TextureD3D_2D::getRenderTargetSerial(const gl::ImageIndex &index)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700773{
Jamie Madillac7579c2014-09-17 16:59:33 -0400774 ASSERT(!index.hasLayer());
Geoff Langef7b0162014-09-04 13:29:23 -0400775 return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700776}
777
Jamie Madillac7579c2014-09-17 16:59:33 -0400778RenderTarget *TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700779{
Jamie Madillac7579c2014-09-17 16:59:33 -0400780 ASSERT(!index.hasLayer());
Brandon Jonescef06ff2014-08-05 13:27:48 -0700781
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700782 // ensure the underlying texture is created
Geoff Langef7b0162014-09-04 13:29:23 -0400783 gl::Error error = ensureRenderTarget();
784 if (error.isError())
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700785 {
786 return NULL;
787 }
788
Geoff Langef7b0162014-09-04 13:29:23 -0400789 error = updateStorageLevel(index.mipIndex);
790 if (error.isError())
791 {
792 return NULL;
793 }
794
Jamie Madill2f06dbf2014-09-18 15:08:50 -0400795 return mTexStorage->getRenderTarget(index);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700796}
797
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700798bool TextureD3D_2D::isValidLevel(int level) const
799{
800 return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false);
801}
802
803bool TextureD3D_2D::isLevelComplete(int level) const
804{
805 if (isImmutable())
806 {
807 return true;
808 }
809
Brandon Jones78b1acd2014-07-15 15:33:07 -0700810 const Image *baseImage = getBaseLevelImage();
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700811
812 GLsizei width = baseImage->getWidth();
813 GLsizei height = baseImage->getHeight();
814
815 if (width <= 0 || height <= 0)
816 {
817 return false;
818 }
819
820 // The base image level is complete if the width and height are positive
821 if (level == 0)
822 {
823 return true;
824 }
825
826 ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
Brandon Jones78b1acd2014-07-15 15:33:07 -0700827 ImageD3D *image = mImageArray[level];
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700828
829 if (image->getInternalFormat() != baseImage->getInternalFormat())
830 {
831 return false;
832 }
833
834 if (image->getWidth() != std::max(1, width >> level))
835 {
836 return false;
837 }
838
839 if (image->getHeight() != std::max(1, height >> level))
840 {
841 return false;
842 }
843
844 return true;
845}
846
847// Constructs a native texture resource from the texture images
Geoff Langef7b0162014-09-04 13:29:23 -0400848gl::Error TextureD3D_2D::initializeStorage(bool renderTarget)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700849{
850 // Only initialize the first time this texture is used as a render target or shader resource
851 if (mTexStorage)
852 {
Geoff Langef7b0162014-09-04 13:29:23 -0400853 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700854 }
855
856 // do not attempt to create storage for nonexistant data
857 if (!isLevelComplete(0))
858 {
Geoff Langef7b0162014-09-04 13:29:23 -0400859 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700860 }
861
862 bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
863
Geoff Langef7b0162014-09-04 13:29:23 -0400864 TextureStorage *storage = NULL;
865 gl::Error error = createCompleteStorage(createRenderTarget, &storage);
866 if (error.isError())
867 {
868 return error;
869 }
870
871 error = setCompleteTexStorage(storage);
872 if (error.isError())
873 {
874 SafeDelete(storage);
875 return error;
876 }
877
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700878 ASSERT(mTexStorage);
879
880 // flush image data to the storage
Geoff Langef7b0162014-09-04 13:29:23 -0400881 error = updateStorage();
882 if (error.isError())
883 {
884 return error;
885 }
886
887 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700888}
889
Geoff Langef7b0162014-09-04 13:29:23 -0400890gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700891{
892 GLsizei width = getBaseLevelWidth();
893 GLsizei height = getBaseLevelHeight();
Jamie Madillc4833262014-09-18 16:18:26 -0400894 GLenum internalFormat = getBaseLevelInternalFormat();
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700895
896 ASSERT(width > 0 && height > 0);
897
898 // use existing storage level count, when previously specified by TexStorage*D
899 GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
900
Geoff Langef7b0162014-09-04 13:29:23 -0400901 // TODO(geofflang): Determine if the texture creation succeeded
902 *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels);
903
904 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700905}
906
Geoff Langef7b0162014-09-04 13:29:23 -0400907gl::Error TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700908{
Geoff Langef7b0162014-09-04 13:29:23 -0400909 if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700910 {
Geoff Langef7b0162014-09-04 13:29:23 -0400911 for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700912 {
Geoff Langef7b0162014-09-04 13:29:23 -0400913 gl::Error error = mImageArray[level]->setManagedSurface2D(newCompleteTexStorage, level);
914 if (error.isError())
915 {
916 return error;
917 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700918 }
919 }
920
Geoff Langef7b0162014-09-04 13:29:23 -0400921 SafeDelete(mTexStorage);
922 mTexStorage = newCompleteTexStorage;
923
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700924 mDirtyImages = true;
Geoff Langef7b0162014-09-04 13:29:23 -0400925
926 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700927}
928
Geoff Langef7b0162014-09-04 13:29:23 -0400929gl::Error TextureD3D_2D::updateStorage()
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700930{
931 ASSERT(mTexStorage != NULL);
932 GLint storageLevels = mTexStorage->getLevelCount();
933 for (int level = 0; level < storageLevels; level++)
934 {
935 if (mImageArray[level]->isDirty() && isLevelComplete(level))
936 {
Geoff Langef7b0162014-09-04 13:29:23 -0400937 gl::Error error = updateStorageLevel(level);
938 if (error.isError())
939 {
940 return error;
941 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700942 }
943 }
Geoff Langef7b0162014-09-04 13:29:23 -0400944
945 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700946}
947
Geoff Langef7b0162014-09-04 13:29:23 -0400948gl::Error TextureD3D_2D::updateStorageLevel(int level)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700949{
950 ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
951 ASSERT(isLevelComplete(level));
952
953 if (mImageArray[level]->isDirty())
954 {
Jamie Madill7cb2b9d2014-10-02 11:03:13 -0400955 gl::ImageIndex index = gl::ImageIndex::Make2D(level);
956 gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
Geoff Langef7b0162014-09-04 13:29:23 -0400957 gl::Error error = commitRegion(index, region);
958 if (error.isError())
959 {
960 return error;
961 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700962 }
Geoff Langef7b0162014-09-04 13:29:23 -0400963
964 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700965}
966
967void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height)
968{
969 // If there currently is a corresponding storage texture image, it has these parameters
970 const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
971 const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
972 const GLenum storageFormat = getBaseLevelInternalFormat();
973
974 mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false);
975
976 if (mTexStorage)
977 {
978 const int storageLevels = mTexStorage->getLevelCount();
979
980 if ((level >= storageLevels && storageLevels != 0) ||
981 width != storageWidth ||
982 height != storageHeight ||
983 internalformat != storageFormat) // Discard mismatched storage
984 {
985 for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
986 {
987 mImageArray[i]->markDirty();
988 }
989
990 SafeDelete(mTexStorage);
991 mDirtyImages = true;
992 }
993 }
994}
995
Jamie Madill7cb2b9d2014-10-02 11:03:13 -0400996gl::Error TextureD3D_2D::commitRegion(const gl::ImageIndex &index, const gl::Box &region)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700997{
Jamie Madill7cb2b9d2014-10-02 11:03:13 -0400998 ASSERT(!index.hasLayer());
999 GLint level = index.mipIndex;
1000
Brandon Jonesf47bebc2014-07-09 14:28:42 -07001001 if (isValidLevel(level))
1002 {
Brandon Jones78b1acd2014-07-15 15:33:07 -07001003 ImageD3D *image = mImageArray[level];
Jamie Madill6b51c1a2014-10-06 16:31:21 -04001004 gl::Error error = image->copyToStorage2D(mTexStorage, index, region);
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001005 if (error.isError())
Brandon Jonesf47bebc2014-07-09 14:28:42 -07001006 {
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001007 return error;
Brandon Jonesf47bebc2014-07-09 14:28:42 -07001008 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001009
1010 image->markClean();
Brandon Jonesf47bebc2014-07-09 14:28:42 -07001011 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001012
1013 return gl::Error(GL_NO_ERROR);
Brandon Jonesf47bebc2014-07-09 14:28:42 -07001014}
1015
Jamie Madillef4ac5b2014-09-29 10:46:11 -04001016gl::ImageIndexIterator TextureD3D_2D::imageIterator() const
1017{
1018 return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount());
1019}
Brandon Jones0511e802014-07-14 16:27:26 -07001020
Jamie Madillcb83dc12014-09-29 10:46:12 -04001021gl::ImageIndex TextureD3D_2D::getImageIndex(GLint mip, GLint /*layer*/) const
1022{
1023 // "layer" does not apply to 2D Textures.
1024 return gl::ImageIndex::Make2D(mip);
1025}
1026
Brandon Jones78b1acd2014-07-15 15:33:07 -07001027TextureD3D_Cube::TextureD3D_Cube(Renderer *renderer)
Jamie Madill98553e32014-09-30 16:33:50 -04001028 : TextureD3D(renderer)
Brandon Jones0511e802014-07-14 16:27:26 -07001029{
1030 for (int i = 0; i < 6; i++)
1031 {
1032 for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
1033 {
1034 mImageArray[i][j] = ImageD3D::makeImageD3D(renderer->createImage());
1035 }
1036 }
1037}
1038
1039TextureD3D_Cube::~TextureD3D_Cube()
1040{
Austin Kinross69822602014-08-12 15:51:37 -07001041 // Delete the Images before the TextureStorage.
1042 // Images might be relying on the TextureStorage for some of their data.
1043 // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
Brandon Jones0511e802014-07-14 16:27:26 -07001044 for (int i = 0; i < 6; i++)
1045 {
1046 for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
1047 {
1048 SafeDelete(mImageArray[i][j]);
1049 }
1050 }
Austin Kinross69822602014-08-12 15:51:37 -07001051
1052 SafeDelete(mTexStorage);
Brandon Jones0511e802014-07-14 16:27:26 -07001053}
1054
Brandon Jonescef06ff2014-08-05 13:27:48 -07001055Image *TextureD3D_Cube::getImage(int level, int layer) const
Brandon Jones0511e802014-07-14 16:27:26 -07001056{
1057 ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
Brandon Jonescef06ff2014-08-05 13:27:48 -07001058 ASSERT(layer < 6);
1059 return mImageArray[layer][level];
Brandon Jones0511e802014-07-14 16:27:26 -07001060}
1061
Jamie Madillfeda4d22014-09-17 13:03:29 -04001062Image *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const
1063{
1064 ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1065 ASSERT(index.layerIndex < 6);
1066 return mImageArray[index.layerIndex][index.mipIndex];
1067}
1068
Brandon Jonescef06ff2014-08-05 13:27:48 -07001069GLsizei TextureD3D_Cube::getLayerCount(int level) const
Brandon Jones0511e802014-07-14 16:27:26 -07001070{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001071 ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1072 return 6;
Brandon Jones0511e802014-07-14 16:27:26 -07001073}
1074
Brandon Jonescef06ff2014-08-05 13:27:48 -07001075GLenum TextureD3D_Cube::getInternalFormat(GLint level, GLint layer) const
Brandon Jones0511e802014-07-14 16:27:26 -07001076{
1077 if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonescef06ff2014-08-05 13:27:48 -07001078 return mImageArray[layer][level]->getInternalFormat();
Brandon Jones0511e802014-07-14 16:27:26 -07001079 else
1080 return GL_NONE;
1081}
1082
Brandon Jonescef06ff2014-08-05 13:27:48 -07001083bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const
Brandon Jones0511e802014-07-14 16:27:26 -07001084{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001085 return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0;
Brandon Jones0511e802014-07-14 16:27:26 -07001086}
1087
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001088gl::Error TextureD3D_Cube::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
1089 GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
1090 const void *pixels)
Brandon Jones0511e802014-07-14 16:27:26 -07001091{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001092 ASSERT(depth == 1);
1093
Geoff Lang5d601382014-07-22 15:14:06 -04001094 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
Jamie Madillba6bc952014-10-06 10:56:22 -04001095 gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
Brandon Jones0511e802014-07-14 16:27:26 -07001096
Jamie Madillba6bc952014-10-06 10:56:22 -04001097 redefineImage(index.layerIndex, level, sizedInternalFormat, width, height);
Brandon Jones0511e802014-07-14 16:27:26 -07001098
Jamie Madillba6bc952014-10-06 10:56:22 -04001099 return TextureD3D::setImage(unpack, type, pixels, index);
Brandon Jones0511e802014-07-14 16:27:26 -07001100}
1101
Geoff Langb5348332014-09-02 13:16:34 -04001102gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format,
1103 GLsizei width, GLsizei height, GLsizei depth,
1104 GLsizei imageSize, const void *pixels)
Brandon Jones0511e802014-07-14 16:27:26 -07001105{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001106 ASSERT(depth == 1);
1107
Brandon Jones0511e802014-07-14 16:27:26 -07001108 // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
Brandon Jonescef06ff2014-08-05 13:27:48 -07001109 int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
1110
Brandon Jones0511e802014-07-14 16:27:26 -07001111 redefineImage(faceIndex, level, format, width, height);
1112
Geoff Langb5348332014-09-02 13:16:34 -04001113 return TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[faceIndex][level]);
Brandon Jones0511e802014-07-14 16:27:26 -07001114}
1115
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001116gl::Error TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1117 GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
1118 const gl::PixelUnpackState &unpack, const void *pixels)
Brandon Jones0511e802014-07-14 16:27:26 -07001119{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001120 ASSERT(depth == 1 && zoffset == 0);
Jamie Madillfeda4d22014-09-17 13:03:29 -04001121 gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
Jamie Madille6b6da02014-10-02 11:03:14 -04001122 return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index);
Brandon Jones0511e802014-07-14 16:27:26 -07001123}
1124
Geoff Langb5348332014-09-02 13:16:34 -04001125gl::Error TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1126 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1127 GLsizei imageSize, const void *pixels)
Brandon Jones0511e802014-07-14 16:27:26 -07001128{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001129 ASSERT(depth == 1 && zoffset == 0);
1130
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04001131 gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
Brandon Jonescef06ff2014-08-05 13:27:48 -07001132
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04001133 gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[index.layerIndex][level]);
Geoff Langb5348332014-09-02 13:16:34 -04001134 if (error.isError())
Brandon Jones0511e802014-07-14 16:27:26 -07001135 {
Geoff Langb5348332014-09-02 13:16:34 -04001136 return error;
Brandon Jones0511e802014-07-14 16:27:26 -07001137 }
Geoff Langb5348332014-09-02 13:16:34 -04001138
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04001139 gl::Box region(xoffset, yoffset, 0, width, height, 1);
1140 return commitRegion(index, region);
Brandon Jones0511e802014-07-14 16:27:26 -07001141}
1142
Geoff Langef7b0162014-09-04 13:29:23 -04001143gl::Error TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y,
1144 GLsizei width, GLsizei height, gl::Framebuffer *source)
Brandon Jones0511e802014-07-14 16:27:26 -07001145{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001146 int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
Geoff Lang5d601382014-07-22 15:14:06 -04001147 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
1148
Brandon Jones0511e802014-07-14 16:27:26 -07001149 redefineImage(faceIndex, level, sizedInternalFormat, width, height);
1150
Jamie Madill82bf0c52014-10-03 11:50:53 -04001151 gl::Rectangle sourceRect(x, y, width, height);
1152
Brandon Jones0511e802014-07-14 16:27:26 -07001153 if (!mImageArray[faceIndex][level]->isRenderableFormat())
1154 {
Geoff Langef7b0162014-09-04 13:29:23 -04001155 gl::Error error = mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source);
1156 if (error.isError())
1157 {
1158 return error;
1159 }
1160
Brandon Jones0511e802014-07-14 16:27:26 -07001161 mDirtyImages = true;
1162 }
1163 else
1164 {
Geoff Langef7b0162014-09-04 13:29:23 -04001165 gl::Error error = ensureRenderTarget();
1166 if (error.isError())
1167 {
1168 return error;
1169 }
1170
Brandon Jones0511e802014-07-14 16:27:26 -07001171 mImageArray[faceIndex][level]->markClean();
1172
1173 ASSERT(width == height);
1174
1175 if (width > 0 && isValidFaceLevel(faceIndex, level))
1176 {
Geoff Langef7b0162014-09-04 13:29:23 -04001177 error = mRenderer->copyImageCube(source, sourceRect, format, 0, 0, mTexStorage, target, level);
1178 if (error.isError())
1179 {
1180 return error;
1181 }
Brandon Jones0511e802014-07-14 16:27:26 -07001182 }
1183 }
Geoff Langef7b0162014-09-04 13:29:23 -04001184
1185 return gl::Error(GL_NO_ERROR);
Brandon Jones0511e802014-07-14 16:27:26 -07001186}
1187
Geoff Langef7b0162014-09-04 13:29:23 -04001188gl::Error TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1189 GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
Brandon Jones0511e802014-07-14 16:27:26 -07001190{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001191 int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
Brandon Jones0511e802014-07-14 16:27:26 -07001192
1193 // We can only make our texture storage to a render target if the level we're copying *to* is complete
1194 // and the base level is cube-complete. The base level must be cube complete (common case) because we cannot
1195 // rely on the "getBaseLevel*" methods reliably otherwise.
1196 bool canCreateRenderTarget = isFaceLevelComplete(faceIndex, level) && isCubeComplete();
1197
Jamie Madill82bf0c52014-10-03 11:50:53 -04001198 gl::Rectangle sourceRect(x, y, width, height);
1199
Brandon Jones0511e802014-07-14 16:27:26 -07001200 if (!mImageArray[faceIndex][level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
1201 {
Geoff Langef7b0162014-09-04 13:29:23 -04001202 gl::Error error =mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source);
1203 if (error.isError())
1204 {
1205 return error;
1206 }
1207
Brandon Jones0511e802014-07-14 16:27:26 -07001208 mDirtyImages = true;
1209 }
1210 else
1211 {
Geoff Langef7b0162014-09-04 13:29:23 -04001212 gl::Error error = ensureRenderTarget();
1213 if (error.isError())
1214 {
1215 return error;
1216 }
Brandon Jones0511e802014-07-14 16:27:26 -07001217
1218 if (isValidFaceLevel(faceIndex, level))
1219 {
Geoff Langef7b0162014-09-04 13:29:23 -04001220 error = updateStorageFaceLevel(faceIndex, level);
1221 if (error.isError())
1222 {
1223 return error;
1224 }
Brandon Jones0511e802014-07-14 16:27:26 -07001225
Geoff Langef7b0162014-09-04 13:29:23 -04001226 error = mRenderer->copyImageCube(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
1227 xoffset, yoffset, mTexStorage, target, level);
1228 if (error.isError())
1229 {
1230 return error;
1231 }
Brandon Jones0511e802014-07-14 16:27:26 -07001232 }
1233 }
Geoff Langef7b0162014-09-04 13:29:23 -04001234
1235 return gl::Error(GL_NO_ERROR);
Brandon Jones0511e802014-07-14 16:27:26 -07001236}
1237
Brandon Jonescef06ff2014-08-05 13:27:48 -07001238void TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
Brandon Jones0511e802014-07-14 16:27:26 -07001239{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001240 ASSERT(width == height);
1241 ASSERT(depth == 1);
1242
Brandon Jones0511e802014-07-14 16:27:26 -07001243 for (int level = 0; level < levels; level++)
1244 {
Brandon Jonescef06ff2014-08-05 13:27:48 -07001245 GLsizei mipSize = std::max(1, width >> level);
Brandon Jones0511e802014-07-14 16:27:26 -07001246 for (int faceIndex = 0; faceIndex < 6; faceIndex++)
1247 {
1248 mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, mipSize, mipSize, 1, true);
1249 }
1250 }
1251
1252 for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
1253 {
1254 for (int faceIndex = 0; faceIndex < 6; faceIndex++)
1255 {
1256 mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, GL_NONE, 0, 0, 0, true);
1257 }
1258 }
1259
1260 mImmutable = true;
1261
Jamie Madillc4833262014-09-18 16:18:26 -04001262 bool renderTarget = IsRenderTargetUsage(mUsage);
Jamie Madill2f06dbf2014-09-18 15:08:50 -04001263 TextureStorage *storage = mRenderer->createTextureStorageCube(internalformat, renderTarget, width, levels);
1264 setCompleteTexStorage(storage);
Brandon Jones0511e802014-07-14 16:27:26 -07001265}
1266
Brandon Jones0511e802014-07-14 16:27:26 -07001267// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
1268bool TextureD3D_Cube::isCubeComplete() const
1269{
1270 int baseWidth = getBaseLevelWidth();
1271 int baseHeight = getBaseLevelHeight();
1272 GLenum baseFormat = getBaseLevelInternalFormat();
1273
1274 if (baseWidth <= 0 || baseWidth != baseHeight)
1275 {
1276 return false;
1277 }
1278
1279 for (int faceIndex = 1; faceIndex < 6; faceIndex++)
1280 {
1281 const ImageD3D &faceBaseImage = *mImageArray[faceIndex][0];
1282
1283 if (faceBaseImage.getWidth() != baseWidth ||
1284 faceBaseImage.getHeight() != baseHeight ||
1285 faceBaseImage.getInternalFormat() != baseFormat )
1286 {
1287 return false;
1288 }
1289 }
1290
1291 return true;
1292}
1293
Brandon Jones6053a522014-07-25 16:22:09 -07001294void TextureD3D_Cube::bindTexImage(egl::Surface *surface)
1295{
1296 UNREACHABLE();
1297}
1298
1299void TextureD3D_Cube::releaseTexImage()
1300{
1301 UNREACHABLE();
1302}
1303
1304
Jamie Madill4aa79e12014-09-29 10:46:14 -04001305void TextureD3D_Cube::initMipmapsImages()
Brandon Jones0511e802014-07-14 16:27:26 -07001306{
1307 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
1308 int levelCount = mipLevels();
1309 for (int faceIndex = 0; faceIndex < 6; faceIndex++)
1310 {
1311 for (int level = 1; level < levelCount; level++)
1312 {
1313 int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1));
1314 redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), faceLevelSize, faceLevelSize);
1315 }
1316 }
Brandon Jones0511e802014-07-14 16:27:26 -07001317}
1318
Jamie Madillac7579c2014-09-17 16:59:33 -04001319unsigned int TextureD3D_Cube::getRenderTargetSerial(const gl::ImageIndex &index)
Brandon Jones0511e802014-07-14 16:27:26 -07001320{
Geoff Langef7b0162014-09-04 13:29:23 -04001321 return (ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
Brandon Jones0511e802014-07-14 16:27:26 -07001322}
1323
Jamie Madillac7579c2014-09-17 16:59:33 -04001324RenderTarget *TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index)
Brandon Jones0511e802014-07-14 16:27:26 -07001325{
Jamie Madillac7579c2014-09-17 16:59:33 -04001326 ASSERT(gl::IsCubemapTextureTarget(index.type));
Brandon Jones0511e802014-07-14 16:27:26 -07001327
1328 // ensure the underlying texture is created
Geoff Langef7b0162014-09-04 13:29:23 -04001329 gl::Error error = ensureRenderTarget();
1330 if (error.isError())
Brandon Jones0511e802014-07-14 16:27:26 -07001331 {
1332 return NULL;
1333 }
1334
Geoff Langef7b0162014-09-04 13:29:23 -04001335 error = updateStorageFaceLevel(index.layerIndex, index.mipIndex);
1336 if (error.isError())
1337 {
1338 return NULL;
1339 }
1340
Jamie Madill2f06dbf2014-09-18 15:08:50 -04001341 return mTexStorage->getRenderTarget(index);
Brandon Jones0511e802014-07-14 16:27:26 -07001342}
1343
Geoff Langef7b0162014-09-04 13:29:23 -04001344gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget)
Brandon Jones0511e802014-07-14 16:27:26 -07001345{
1346 // Only initialize the first time this texture is used as a render target or shader resource
1347 if (mTexStorage)
1348 {
Geoff Langef7b0162014-09-04 13:29:23 -04001349 return gl::Error(GL_NO_ERROR);
Brandon Jones0511e802014-07-14 16:27:26 -07001350 }
1351
1352 // do not attempt to create storage for nonexistant data
1353 if (!isFaceLevelComplete(0, 0))
1354 {
Geoff Langef7b0162014-09-04 13:29:23 -04001355 return gl::Error(GL_NO_ERROR);
Brandon Jones0511e802014-07-14 16:27:26 -07001356 }
1357
1358 bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
1359
Geoff Langef7b0162014-09-04 13:29:23 -04001360 TextureStorage *storage = NULL;
1361 gl::Error error = createCompleteStorage(createRenderTarget, &storage);
1362 if (error.isError())
1363 {
1364 return error;
1365 }
1366
1367 error = setCompleteTexStorage(storage);
1368 if (error.isError())
1369 {
1370 SafeDelete(storage);
1371 return error;
1372 }
1373
Brandon Jones0511e802014-07-14 16:27:26 -07001374 ASSERT(mTexStorage);
1375
1376 // flush image data to the storage
Geoff Langef7b0162014-09-04 13:29:23 -04001377 error = updateStorage();
1378 if (error.isError())
1379 {
1380 return error;
1381 }
1382
1383 return gl::Error(GL_NO_ERROR);
Brandon Jones0511e802014-07-14 16:27:26 -07001384}
1385
Geoff Langef7b0162014-09-04 13:29:23 -04001386gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const
Brandon Jones0511e802014-07-14 16:27:26 -07001387{
1388 GLsizei size = getBaseLevelWidth();
1389
1390 ASSERT(size > 0);
1391
1392 // use existing storage level count, when previously specified by TexStorage*D
1393 GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1));
1394
Geoff Langef7b0162014-09-04 13:29:23 -04001395 // TODO (geofflang): detect if storage creation succeeded
1396 *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels);
1397
1398 return gl::Error(GL_NO_ERROR);
Brandon Jones0511e802014-07-14 16:27:26 -07001399}
1400
Geoff Langef7b0162014-09-04 13:29:23 -04001401gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
Brandon Jones0511e802014-07-14 16:27:26 -07001402{
Geoff Langef7b0162014-09-04 13:29:23 -04001403 if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
Brandon Jones0511e802014-07-14 16:27:26 -07001404 {
1405 for (int faceIndex = 0; faceIndex < 6; faceIndex++)
1406 {
Geoff Langef7b0162014-09-04 13:29:23 -04001407 for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
Brandon Jones0511e802014-07-14 16:27:26 -07001408 {
Geoff Langef7b0162014-09-04 13:29:23 -04001409 gl::Error error = mImageArray[faceIndex][level]->setManagedSurfaceCube(newCompleteTexStorage, faceIndex, level);
1410 if (error.isError())
1411 {
1412 return error;
1413 }
Brandon Jones0511e802014-07-14 16:27:26 -07001414 }
1415 }
1416 }
1417
Geoff Langef7b0162014-09-04 13:29:23 -04001418 SafeDelete(mTexStorage);
1419 mTexStorage = newCompleteTexStorage;
1420
Brandon Jones0511e802014-07-14 16:27:26 -07001421 mDirtyImages = true;
Geoff Langef7b0162014-09-04 13:29:23 -04001422 return gl::Error(GL_NO_ERROR);
Brandon Jones0511e802014-07-14 16:27:26 -07001423}
1424
Geoff Langef7b0162014-09-04 13:29:23 -04001425gl::Error TextureD3D_Cube::updateStorage()
Brandon Jones0511e802014-07-14 16:27:26 -07001426{
1427 ASSERT(mTexStorage != NULL);
1428 GLint storageLevels = mTexStorage->getLevelCount();
1429 for (int face = 0; face < 6; face++)
1430 {
1431 for (int level = 0; level < storageLevels; level++)
1432 {
1433 if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level))
1434 {
Geoff Langef7b0162014-09-04 13:29:23 -04001435 gl::Error error = updateStorageFaceLevel(face, level);
1436 if (error.isError())
1437 {
1438 return error;
1439 }
Brandon Jones0511e802014-07-14 16:27:26 -07001440 }
1441 }
1442 }
Geoff Langef7b0162014-09-04 13:29:23 -04001443
1444 return gl::Error(GL_NO_ERROR);
Brandon Jones0511e802014-07-14 16:27:26 -07001445}
1446
Brandon Jones0511e802014-07-14 16:27:26 -07001447bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const
1448{
1449 return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
1450}
1451
Brandon Jones0511e802014-07-14 16:27:26 -07001452bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const
1453{
1454 ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL);
1455
1456 if (isImmutable())
1457 {
1458 return true;
1459 }
1460
1461 int baseSize = getBaseLevelWidth();
1462
1463 if (baseSize <= 0)
1464 {
1465 return false;
1466 }
1467
1468 // "isCubeComplete" checks for base level completeness and we must call that
1469 // to determine if any face at level 0 is complete. We omit that check here
1470 // to avoid re-checking cube-completeness for every face at level 0.
1471 if (level == 0)
1472 {
1473 return true;
1474 }
1475
1476 // Check that non-zero levels are consistent with the base level.
1477 const ImageD3D *faceLevelImage = mImageArray[faceIndex][level];
1478
1479 if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
1480 {
1481 return false;
1482 }
1483
1484 if (faceLevelImage->getWidth() != std::max(1, baseSize >> level))
1485 {
1486 return false;
1487 }
1488
1489 return true;
1490}
1491
Geoff Langef7b0162014-09-04 13:29:23 -04001492gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level)
Brandon Jones0511e802014-07-14 16:27:26 -07001493{
1494 ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL);
1495 ImageD3D *image = mImageArray[faceIndex][level];
1496
1497 if (image->isDirty())
1498 {
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04001499 GLenum faceTarget = gl::TextureCubeMap::layerIndexToTarget(faceIndex);
1500 gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level);
1501 gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1);
Geoff Langef7b0162014-09-04 13:29:23 -04001502 gl::Error error = commitRegion(index, region);
1503 if (error.isError())
1504 {
1505 return error;
1506 }
Brandon Jones0511e802014-07-14 16:27:26 -07001507 }
Geoff Langef7b0162014-09-04 13:29:23 -04001508
1509 return gl::Error(GL_NO_ERROR);
Brandon Jones0511e802014-07-14 16:27:26 -07001510}
1511
1512void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height)
1513{
1514 // If there currently is a corresponding storage texture image, it has these parameters
1515 const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
1516 const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
1517 const GLenum storageFormat = getBaseLevelInternalFormat();
1518
1519 mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, width, height, 1, false);
1520
1521 if (mTexStorage)
1522 {
1523 const int storageLevels = mTexStorage->getLevelCount();
1524
1525 if ((level >= storageLevels && storageLevels != 0) ||
1526 width != storageWidth ||
1527 height != storageHeight ||
1528 internalformat != storageFormat) // Discard mismatched storage
1529 {
1530 for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
1531 {
1532 for (int faceIndex = 0; faceIndex < 6; faceIndex++)
1533 {
1534 mImageArray[faceIndex][level]->markDirty();
1535 }
1536 }
1537
1538 SafeDelete(mTexStorage);
1539
1540 mDirtyImages = true;
1541 }
1542 }
1543}
1544
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04001545gl::Error TextureD3D_Cube::commitRegion(const gl::ImageIndex &index, const gl::Box &region)
Brandon Jones0511e802014-07-14 16:27:26 -07001546{
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04001547 ASSERT(index.hasLayer());
1548
1549 GLint level = index.mipIndex;
1550 int faceIndex = static_cast<int>(index.layerIndex);
1551
Brandon Jones0511e802014-07-14 16:27:26 -07001552 if (isValidFaceLevel(faceIndex, level))
1553 {
1554 ImageD3D *image = mImageArray[faceIndex][level];
Jamie Madill6b51c1a2014-10-06 16:31:21 -04001555 gl::Error error = image->copyToStorageCube(mTexStorage, index, region);
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001556 if (error.isError())
1557 {
1558 return error;
1559 }
1560
1561 image->markClean();
Brandon Jones0511e802014-07-14 16:27:26 -07001562 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001563
1564 return gl::Error(GL_NO_ERROR);
Brandon Jones0511e802014-07-14 16:27:26 -07001565}
1566
Jamie Madillef4ac5b2014-09-29 10:46:11 -04001567gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const
1568{
1569 return gl::ImageIndexIterator::MakeCube(0, mTexStorage->getLevelCount());
1570}
Brandon Jones78b1acd2014-07-15 15:33:07 -07001571
Jamie Madillcb83dc12014-09-29 10:46:12 -04001572gl::ImageIndex TextureD3D_Cube::getImageIndex(GLint mip, GLint layer) const
1573{
1574 // The "layer" of the image index corresponds to the cube face
1575 return gl::ImageIndex::MakeCube(gl::TextureCubeMap::layerIndexToTarget(layer), mip);
1576}
1577
Brandon Jones78b1acd2014-07-15 15:33:07 -07001578TextureD3D_3D::TextureD3D_3D(Renderer *renderer)
Jamie Madill98553e32014-09-30 16:33:50 -04001579 : TextureD3D(renderer)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001580{
1581 for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
1582 {
1583 mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage());
1584 }
1585}
1586
1587TextureD3D_3D::~TextureD3D_3D()
1588{
Austin Kinross69822602014-08-12 15:51:37 -07001589 // Delete the Images before the TextureStorage.
1590 // Images might be relying on the TextureStorage for some of their data.
1591 // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
Brandon Jones78b1acd2014-07-15 15:33:07 -07001592 for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
1593 {
1594 delete mImageArray[i];
1595 }
Austin Kinross69822602014-08-12 15:51:37 -07001596
1597 SafeDelete(mTexStorage);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001598}
1599
Brandon Jonescef06ff2014-08-05 13:27:48 -07001600Image *TextureD3D_3D::getImage(int level, int layer) const
Brandon Jones78b1acd2014-07-15 15:33:07 -07001601{
1602 ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
Brandon Jonescef06ff2014-08-05 13:27:48 -07001603 ASSERT(layer == 0);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001604 return mImageArray[level];
1605}
1606
Jamie Madillfeda4d22014-09-17 13:03:29 -04001607Image *TextureD3D_3D::getImage(const gl::ImageIndex &index) const
1608{
1609 ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
Jamie Madillac7579c2014-09-17 16:59:33 -04001610 ASSERT(!index.hasLayer());
Jamie Madillfeda4d22014-09-17 13:03:29 -04001611 ASSERT(index.type == GL_TEXTURE_3D);
1612 return mImageArray[index.mipIndex];
1613}
1614
Brandon Jonescef06ff2014-08-05 13:27:48 -07001615GLsizei TextureD3D_3D::getLayerCount(int level) const
Brandon Jones78b1acd2014-07-15 15:33:07 -07001616{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001617 ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
1618 return 1;
Brandon Jones78b1acd2014-07-15 15:33:07 -07001619}
1620
Brandon Jones78b1acd2014-07-15 15:33:07 -07001621GLsizei TextureD3D_3D::getWidth(GLint level) const
1622{
1623 if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1624 return mImageArray[level]->getWidth();
1625 else
1626 return 0;
1627}
1628
1629GLsizei TextureD3D_3D::getHeight(GLint level) const
1630{
1631 if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1632 return mImageArray[level]->getHeight();
1633 else
1634 return 0;
1635}
1636
1637GLsizei TextureD3D_3D::getDepth(GLint level) const
1638{
1639 if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1640 return mImageArray[level]->getDepth();
1641 else
1642 return 0;
1643}
1644
1645GLenum TextureD3D_3D::getInternalFormat(GLint level) const
1646{
1647 if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1648 return mImageArray[level]->getInternalFormat();
1649 else
1650 return GL_NONE;
1651}
1652
1653bool TextureD3D_3D::isDepth(GLint level) const
1654{
Geoff Lang5d601382014-07-22 15:14:06 -04001655 return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
Brandon Jones78b1acd2014-07-15 15:33:07 -07001656}
1657
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001658gl::Error TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
1659 GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
1660 const void *pixels)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001661{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001662 ASSERT(target == GL_TEXTURE_3D);
Geoff Lang5d601382014-07-22 15:14:06 -04001663 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
1664
Brandon Jones78b1acd2014-07-15 15:33:07 -07001665 redefineImage(level, sizedInternalFormat, width, height, depth);
1666
1667 bool fastUnpacked = false;
1668
Jamie Madillba6bc952014-10-06 10:56:22 -04001669 gl::ImageIndex index = gl::ImageIndex::Make3D(level);
1670
Brandon Jones78b1acd2014-07-15 15:33:07 -07001671 // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
1672 if (isFastUnpackable(unpack, sizedInternalFormat))
1673 {
1674 // Will try to create RT storage if it does not exist
Jamie Madillac7579c2014-09-17 16:59:33 -04001675 RenderTarget *destRenderTarget = getRenderTarget(index);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001676 gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
1677
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001678 if (destRenderTarget)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001679 {
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001680 gl::Error error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget);
1681 if (error.isError())
1682 {
1683 return error;
1684 }
1685
Brandon Jones78b1acd2014-07-15 15:33:07 -07001686 // Ensure we don't overwrite our newly initialized data
1687 mImageArray[level]->markClean();
1688
1689 fastUnpacked = true;
1690 }
1691 }
1692
1693 if (!fastUnpacked)
1694 {
Jamie Madillba6bc952014-10-06 10:56:22 -04001695 gl::Error error = TextureD3D::setImage(unpack, type, pixels, index);
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001696 if (error.isError())
1697 {
1698 return error;
1699 }
Brandon Jones78b1acd2014-07-15 15:33:07 -07001700 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001701
1702 return gl::Error(GL_NO_ERROR);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001703}
1704
Geoff Langb5348332014-09-02 13:16:34 -04001705gl::Error TextureD3D_3D::setCompressedImage(GLenum target, GLint level, GLenum format,
1706 GLsizei width, GLsizei height,GLsizei depth,
1707 GLsizei imageSize, const void *pixels)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001708{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001709 ASSERT(target == GL_TEXTURE_3D);
1710
Brandon Jones78b1acd2014-07-15 15:33:07 -07001711 // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
1712 redefineImage(level, format, width, height, depth);
1713
Geoff Langb5348332014-09-02 13:16:34 -04001714 return TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001715}
1716
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001717gl::Error TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1718 GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
1719 const gl::PixelUnpackState &unpack, const void *pixels)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001720{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001721 ASSERT(target == GL_TEXTURE_3D);
1722
Brandon Jones78b1acd2014-07-15 15:33:07 -07001723 bool fastUnpacked = false;
1724
Jamie Madillac7579c2014-09-17 16:59:33 -04001725 gl::ImageIndex index = gl::ImageIndex::Make3D(level);
1726
Brandon Jones78b1acd2014-07-15 15:33:07 -07001727 // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
1728 if (isFastUnpackable(unpack, getInternalFormat(level)))
1729 {
Jamie Madillac7579c2014-09-17 16:59:33 -04001730 RenderTarget *destRenderTarget = getRenderTarget(index);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001731
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001732 if (destRenderTarget)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001733 {
Jamie Madille6b6da02014-10-02 11:03:14 -04001734 gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth);
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001735 gl::Error error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget);
1736 if (error.isError())
1737 {
1738 return error;
1739 }
1740
Brandon Jones78b1acd2014-07-15 15:33:07 -07001741 // Ensure we don't overwrite our newly initialized data
1742 mImageArray[level]->markClean();
1743
1744 fastUnpacked = true;
1745 }
1746 }
1747
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001748 if (!fastUnpacked)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001749 {
Jamie Madille6b6da02014-10-02 11:03:14 -04001750 return TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type,
1751 unpack, pixels, index);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001752 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04001753
1754 return gl::Error(GL_NO_ERROR);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001755}
1756
Geoff Langb5348332014-09-02 13:16:34 -04001757gl::Error TextureD3D_3D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1758 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
1759 GLsizei imageSize, const void *pixels)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001760{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001761 ASSERT(target == GL_TEXTURE_3D);
1762
Geoff Langb5348332014-09-02 13:16:34 -04001763 gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth,
1764 format, imageSize, pixels, mImageArray[level]);
1765 if (error.isError())
Brandon Jones78b1acd2014-07-15 15:33:07 -07001766 {
Geoff Langb5348332014-09-02 13:16:34 -04001767 return error;
Brandon Jones78b1acd2014-07-15 15:33:07 -07001768 }
Geoff Langb5348332014-09-02 13:16:34 -04001769
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04001770 gl::ImageIndex index = gl::ImageIndex::Make3D(level);
1771 gl::Box region(xoffset, yoffset, zoffset, width, height, depth);
1772 return commitRegion(index, region);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001773}
1774
Geoff Langef7b0162014-09-04 13:29:23 -04001775gl::Error TextureD3D_3D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y,
1776 GLsizei width, GLsizei height, gl::Framebuffer *source)
Brandon Jonescef06ff2014-08-05 13:27:48 -07001777{
1778 UNIMPLEMENTED();
Geoff Langef7b0162014-09-04 13:29:23 -04001779 return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented.");
Brandon Jonescef06ff2014-08-05 13:27:48 -07001780}
1781
Geoff Langef7b0162014-09-04 13:29:23 -04001782gl::Error TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
1783 GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001784{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001785 ASSERT(target == GL_TEXTURE_3D);
1786
Brandon Jones78b1acd2014-07-15 15:33:07 -07001787 // can only make our texture storage to a render target if level 0 is defined (with a width & height) and
1788 // the current level we're copying to is defined (with appropriate format, width & height)
1789 bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
1790
Jamie Madill82bf0c52014-10-03 11:50:53 -04001791 gl::Rectangle sourceRect(x, y, width, height);
1792
Brandon Jones78b1acd2014-07-15 15:33:07 -07001793 if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
1794 {
Geoff Langef7b0162014-09-04 13:29:23 -04001795 gl::Error error = mImageArray[level]->copy(xoffset, yoffset, zoffset, sourceRect, source);
1796 if (error.isError())
1797 {
1798 return error;
1799 }
1800
Brandon Jones78b1acd2014-07-15 15:33:07 -07001801 mDirtyImages = true;
1802 }
1803 else
1804 {
Geoff Langef7b0162014-09-04 13:29:23 -04001805 gl::Error error = ensureRenderTarget();
1806 if (error.isError())
1807 {
1808 return error;
1809 }
Brandon Jones78b1acd2014-07-15 15:33:07 -07001810
1811 if (isValidLevel(level))
1812 {
Geoff Langef7b0162014-09-04 13:29:23 -04001813 error = updateStorageLevel(level);
1814 if (error.isError())
1815 {
1816 return error;
1817 }
Brandon Jones78b1acd2014-07-15 15:33:07 -07001818
Geoff Langef7b0162014-09-04 13:29:23 -04001819 error = mRenderer->copyImage3D(source, sourceRect,
1820 gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
1821 xoffset, yoffset, zoffset, mTexStorage, level);
1822 if (error.isError())
1823 {
1824 return error;
1825 }
Brandon Jones78b1acd2014-07-15 15:33:07 -07001826 }
1827 }
Geoff Langef7b0162014-09-04 13:29:23 -04001828
1829 return gl::Error(GL_NO_ERROR);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001830}
1831
Brandon Jonescef06ff2014-08-05 13:27:48 -07001832void TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001833{
Brandon Jonescef06ff2014-08-05 13:27:48 -07001834 ASSERT(target == GL_TEXTURE_3D);
1835
Brandon Jones78b1acd2014-07-15 15:33:07 -07001836 for (int level = 0; level < levels; level++)
1837 {
1838 GLsizei levelWidth = std::max(1, width >> level);
1839 GLsizei levelHeight = std::max(1, height >> level);
1840 GLsizei levelDepth = std::max(1, depth >> level);
1841 mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, levelWidth, levelHeight, levelDepth, true);
1842 }
1843
1844 for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
1845 {
1846 mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true);
1847 }
1848
1849 mImmutable = true;
1850
Jamie Madillc4833262014-09-18 16:18:26 -04001851 bool renderTarget = IsRenderTargetUsage(mUsage);
1852 TextureStorage *storage = mRenderer->createTextureStorage3D(internalformat, renderTarget, width, height, depth, levels);
Jamie Madill2f06dbf2014-09-18 15:08:50 -04001853 setCompleteTexStorage(storage);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001854}
1855
Brandon Jones6053a522014-07-25 16:22:09 -07001856void TextureD3D_3D::bindTexImage(egl::Surface *surface)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001857{
Brandon Jones6053a522014-07-25 16:22:09 -07001858 UNREACHABLE();
Brandon Jones78b1acd2014-07-15 15:33:07 -07001859}
1860
Brandon Jones6053a522014-07-25 16:22:09 -07001861void TextureD3D_3D::releaseTexImage()
Brandon Jones78b1acd2014-07-15 15:33:07 -07001862{
Brandon Jones6053a522014-07-25 16:22:09 -07001863 UNREACHABLE();
Brandon Jones78b1acd2014-07-15 15:33:07 -07001864}
1865
Brandon Jones6053a522014-07-25 16:22:09 -07001866
Jamie Madill4aa79e12014-09-29 10:46:14 -04001867void TextureD3D_3D::initMipmapsImages()
Brandon Jones78b1acd2014-07-15 15:33:07 -07001868{
1869 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
1870 int levelCount = mipLevels();
1871 for (int level = 1; level < levelCount; level++)
1872 {
1873 redefineImage(level, getBaseLevelInternalFormat(),
1874 std::max(getBaseLevelWidth() >> level, 1),
1875 std::max(getBaseLevelHeight() >> level, 1),
1876 std::max(getBaseLevelDepth() >> level, 1));
1877 }
Brandon Jones78b1acd2014-07-15 15:33:07 -07001878}
1879
Jamie Madillac7579c2014-09-17 16:59:33 -04001880unsigned int TextureD3D_3D::getRenderTargetSerial(const gl::ImageIndex &index)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001881{
Geoff Langef7b0162014-09-04 13:29:23 -04001882 return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001883}
1884
Jamie Madillac7579c2014-09-17 16:59:33 -04001885RenderTarget *TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001886{
1887 // ensure the underlying texture is created
Geoff Langef7b0162014-09-04 13:29:23 -04001888 gl::Error error = ensureRenderTarget();
1889 if (error.isError())
Brandon Jones78b1acd2014-07-15 15:33:07 -07001890 {
1891 return NULL;
1892 }
1893
Jamie Madillac7579c2014-09-17 16:59:33 -04001894 if (index.hasLayer())
Brandon Jones78b1acd2014-07-15 15:33:07 -07001895 {
Geoff Langef7b0162014-09-04 13:29:23 -04001896 error = updateStorage();
1897 if (error.isError())
1898 {
1899 return NULL;
1900 }
Jamie Madillac7579c2014-09-17 16:59:33 -04001901 }
1902 else
1903 {
Geoff Langef7b0162014-09-04 13:29:23 -04001904 error = updateStorageLevel(index.mipIndex);
1905 if (error.isError())
1906 {
1907 return NULL;
1908 }
Brandon Jones78b1acd2014-07-15 15:33:07 -07001909 }
1910
Jamie Madill2f06dbf2014-09-18 15:08:50 -04001911 return mTexStorage->getRenderTarget(index);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001912}
1913
Geoff Langef7b0162014-09-04 13:29:23 -04001914gl::Error TextureD3D_3D::initializeStorage(bool renderTarget)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001915{
1916 // Only initialize the first time this texture is used as a render target or shader resource
1917 if (mTexStorage)
1918 {
Geoff Langef7b0162014-09-04 13:29:23 -04001919 return gl::Error(GL_NO_ERROR);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001920 }
1921
1922 // do not attempt to create storage for nonexistant data
1923 if (!isLevelComplete(0))
1924 {
Geoff Langef7b0162014-09-04 13:29:23 -04001925 return gl::Error(GL_NO_ERROR);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001926 }
1927
1928 bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
1929
Geoff Langef7b0162014-09-04 13:29:23 -04001930 rx::TextureStorage *storage = NULL;
1931 gl::Error error = createCompleteStorage(createRenderTarget, &storage);
1932 if (error.isError())
1933 {
1934 return error;
1935 }
1936
1937 error = setCompleteTexStorage(storage);
1938 if (error.isError())
1939 {
1940 SafeDelete(storage);
1941 return error;
1942 }
1943
Brandon Jones78b1acd2014-07-15 15:33:07 -07001944 ASSERT(mTexStorage);
1945
1946 // flush image data to the storage
Geoff Langef7b0162014-09-04 13:29:23 -04001947 error = updateStorage();
1948 if (error.isError())
1949 {
1950 return error;
1951 }
1952
1953 return gl::Error(GL_NO_ERROR);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001954}
1955
Geoff Langef7b0162014-09-04 13:29:23 -04001956gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const
Brandon Jones78b1acd2014-07-15 15:33:07 -07001957{
1958 GLsizei width = getBaseLevelWidth();
1959 GLsizei height = getBaseLevelHeight();
1960 GLsizei depth = getBaseLevelDepth();
Jamie Madillc4833262014-09-18 16:18:26 -04001961 GLenum internalFormat = getBaseLevelInternalFormat();
Brandon Jones78b1acd2014-07-15 15:33:07 -07001962
1963 ASSERT(width > 0 && height > 0 && depth > 0);
1964
1965 // use existing storage level count, when previously specified by TexStorage*D
1966 GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth));
1967
Geoff Langef7b0162014-09-04 13:29:23 -04001968 // TODO: Verify creation of the storage succeeded
1969 *outStorage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels);
1970
1971 return gl::Error(GL_NO_ERROR);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001972}
1973
Geoff Langef7b0162014-09-04 13:29:23 -04001974gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
Brandon Jones78b1acd2014-07-15 15:33:07 -07001975{
1976 SafeDelete(mTexStorage);
1977 mTexStorage = newCompleteTexStorage;
1978 mDirtyImages = true;
1979
1980 // We do not support managed 3D storage, as that is D3D9/ES2-only
1981 ASSERT(!mTexStorage->isManaged());
Geoff Langef7b0162014-09-04 13:29:23 -04001982
1983 return gl::Error(GL_NO_ERROR);
Brandon Jones78b1acd2014-07-15 15:33:07 -07001984}
1985
Geoff Langef7b0162014-09-04 13:29:23 -04001986gl::Error TextureD3D_3D::updateStorage()
Brandon Jones78b1acd2014-07-15 15:33:07 -07001987{
1988 ASSERT(mTexStorage != NULL);
1989 GLint storageLevels = mTexStorage->getLevelCount();
1990 for (int level = 0; level < storageLevels; level++)
1991 {
1992 if (mImageArray[level]->isDirty() && isLevelComplete(level))
1993 {
Geoff Langef7b0162014-09-04 13:29:23 -04001994 gl::Error error = updateStorageLevel(level);
1995 if (error.isError())
1996 {
1997 return error;
1998 }
Brandon Jones78b1acd2014-07-15 15:33:07 -07001999 }
2000 }
Geoff Langef7b0162014-09-04 13:29:23 -04002001
2002 return gl::Error(GL_NO_ERROR);
Brandon Jones78b1acd2014-07-15 15:33:07 -07002003}
2004
Brandon Jones78b1acd2014-07-15 15:33:07 -07002005bool TextureD3D_3D::isValidLevel(int level) const
2006{
2007 return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
2008}
2009
2010bool TextureD3D_3D::isLevelComplete(int level) const
2011{
2012 ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
2013
2014 if (isImmutable())
2015 {
2016 return true;
2017 }
2018
2019 GLsizei width = getBaseLevelWidth();
2020 GLsizei height = getBaseLevelHeight();
2021 GLsizei depth = getBaseLevelDepth();
2022
2023 if (width <= 0 || height <= 0 || depth <= 0)
2024 {
2025 return false;
2026 }
2027
2028 if (level == 0)
2029 {
2030 return true;
2031 }
2032
2033 ImageD3D *levelImage = mImageArray[level];
2034
2035 if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
2036 {
2037 return false;
2038 }
2039
2040 if (levelImage->getWidth() != std::max(1, width >> level))
2041 {
2042 return false;
2043 }
2044
2045 if (levelImage->getHeight() != std::max(1, height >> level))
2046 {
2047 return false;
2048 }
2049
2050 if (levelImage->getDepth() != std::max(1, depth >> level))
2051 {
2052 return false;
2053 }
2054
2055 return true;
2056}
2057
Geoff Langef7b0162014-09-04 13:29:23 -04002058gl::Error TextureD3D_3D::updateStorageLevel(int level)
Brandon Jones78b1acd2014-07-15 15:33:07 -07002059{
2060 ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
2061 ASSERT(isLevelComplete(level));
2062
2063 if (mImageArray[level]->isDirty())
2064 {
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04002065 gl::ImageIndex index = gl::ImageIndex::Make3D(level);
2066 gl::Box region(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
Geoff Langef7b0162014-09-04 13:29:23 -04002067 gl::Error error = commitRegion(index, region);
2068 if (error.isError())
2069 {
2070 return error;
2071 }
Brandon Jones78b1acd2014-07-15 15:33:07 -07002072 }
Geoff Langef7b0162014-09-04 13:29:23 -04002073
2074 return gl::Error(GL_NO_ERROR);
Brandon Jones78b1acd2014-07-15 15:33:07 -07002075}
2076
2077void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
2078{
2079 // If there currently is a corresponding storage texture image, it has these parameters
2080 const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
2081 const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
2082 const int storageDepth = std::max(1, getBaseLevelDepth() >> level);
2083 const GLenum storageFormat = getBaseLevelInternalFormat();
2084
2085 mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false);
2086
2087 if (mTexStorage)
2088 {
2089 const int storageLevels = mTexStorage->getLevelCount();
2090
2091 if ((level >= storageLevels && storageLevels != 0) ||
2092 width != storageWidth ||
2093 height != storageHeight ||
2094 depth != storageDepth ||
2095 internalformat != storageFormat) // Discard mismatched storage
2096 {
2097 for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2098 {
2099 mImageArray[i]->markDirty();
2100 }
2101
2102 SafeDelete(mTexStorage);
2103 mDirtyImages = true;
2104 }
2105 }
2106}
2107
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04002108gl::Error TextureD3D_3D::commitRegion(const gl::ImageIndex &index, const gl::Box &region)
Brandon Jones78b1acd2014-07-15 15:33:07 -07002109{
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04002110 ASSERT(!index.hasLayer());
2111 GLint level = index.mipIndex;
2112
Brandon Jones78b1acd2014-07-15 15:33:07 -07002113 if (isValidLevel(level))
2114 {
2115 ImageD3D *image = mImageArray[level];
Jamie Madill6b51c1a2014-10-06 16:31:21 -04002116 gl::Error error = image->copyToStorage3D(mTexStorage, index, region);
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002117 if (error.isError())
Brandon Jones78b1acd2014-07-15 15:33:07 -07002118 {
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002119 return error;
Brandon Jones78b1acd2014-07-15 15:33:07 -07002120 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002121
2122 image->markClean();
Brandon Jones78b1acd2014-07-15 15:33:07 -07002123 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002124
2125 return gl::Error(GL_NO_ERROR);
Brandon Jones78b1acd2014-07-15 15:33:07 -07002126}
2127
Jamie Madillef4ac5b2014-09-29 10:46:11 -04002128gl::ImageIndexIterator TextureD3D_3D::imageIterator() const
2129{
2130 return gl::ImageIndexIterator::Make3D(0, mTexStorage->getLevelCount(),
2131 gl::ImageIndex::ENTIRE_LEVEL, gl::ImageIndex::ENTIRE_LEVEL);
2132}
Brandon Jones142ec422014-07-16 10:31:30 -07002133
Jamie Madillcb83dc12014-09-29 10:46:12 -04002134gl::ImageIndex TextureD3D_3D::getImageIndex(GLint mip, GLint /*layer*/) const
2135{
2136 // The "layer" here does not apply to 3D images. We use one Image per mip.
2137 return gl::ImageIndex::Make3D(mip);
2138}
2139
Brandon Jones142ec422014-07-16 10:31:30 -07002140TextureD3D_2DArray::TextureD3D_2DArray(Renderer *renderer)
Jamie Madill98553e32014-09-30 16:33:50 -04002141 : TextureD3D(renderer)
Brandon Jones142ec422014-07-16 10:31:30 -07002142{
2143 for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
2144 {
2145 mLayerCounts[level] = 0;
2146 mImageArray[level] = NULL;
2147 }
2148}
2149
2150TextureD3D_2DArray::~TextureD3D_2DArray()
2151{
Austin Kinross69822602014-08-12 15:51:37 -07002152 // Delete the Images before the TextureStorage.
2153 // Images might be relying on the TextureStorage for some of their data.
2154 // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
Brandon Jones142ec422014-07-16 10:31:30 -07002155 deleteImages();
Austin Kinross69822602014-08-12 15:51:37 -07002156 SafeDelete(mTexStorage);
Brandon Jones142ec422014-07-16 10:31:30 -07002157}
2158
Brandon Jones142ec422014-07-16 10:31:30 -07002159Image *TextureD3D_2DArray::getImage(int level, int layer) const
2160{
2161 ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2162 ASSERT(layer < mLayerCounts[level]);
2163 return mImageArray[level][layer];
2164}
2165
Jamie Madillfeda4d22014-09-17 13:03:29 -04002166Image *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const
2167{
2168 ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2169 ASSERT(index.layerIndex < mLayerCounts[index.mipIndex]);
2170 ASSERT(index.type == GL_TEXTURE_2D_ARRAY);
2171 return mImageArray[index.mipIndex][index.layerIndex];
2172}
2173
Brandon Jones142ec422014-07-16 10:31:30 -07002174GLsizei TextureD3D_2DArray::getLayerCount(int level) const
2175{
2176 ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
2177 return mLayerCounts[level];
2178}
2179
Brandon Jones142ec422014-07-16 10:31:30 -07002180GLsizei TextureD3D_2DArray::getWidth(GLint level) const
2181{
2182 return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getWidth() : 0;
2183}
2184
2185GLsizei TextureD3D_2DArray::getHeight(GLint level) const
2186{
2187 return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0;
2188}
2189
Brandon Jones142ec422014-07-16 10:31:30 -07002190GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const
2191{
2192 return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE;
2193}
2194
2195bool TextureD3D_2DArray::isDepth(GLint level) const
2196{
Geoff Lang5d601382014-07-22 15:14:06 -04002197 return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
Brandon Jones142ec422014-07-16 10:31:30 -07002198}
2199
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002200gl::Error TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
2201 GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
2202 const void *pixels)
Brandon Jones142ec422014-07-16 10:31:30 -07002203{
Brandon Jonescef06ff2014-08-05 13:27:48 -07002204 ASSERT(target == GL_TEXTURE_2D_ARRAY);
2205
Geoff Lang5d601382014-07-22 15:14:06 -04002206 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
2207
Brandon Jones142ec422014-07-16 10:31:30 -07002208 redefineImage(level, sizedInternalFormat, width, height, depth);
2209
Geoff Lang5d601382014-07-22 15:14:06 -04002210 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
2211 GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment);
Brandon Jones142ec422014-07-16 10:31:30 -07002212
2213 for (int i = 0; i < depth; i++)
2214 {
2215 const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
Jamie Madillba6bc952014-10-06 10:56:22 -04002216 gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
2217 gl::Error error = TextureD3D::setImage(unpack, type, layerPixels, index);
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002218 if (error.isError())
2219 {
2220 return error;
2221 }
Brandon Jones142ec422014-07-16 10:31:30 -07002222 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002223
2224 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002225}
2226
Geoff Langb5348332014-09-02 13:16:34 -04002227gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum format,
2228 GLsizei width, GLsizei height, GLsizei depth,
2229 GLsizei imageSize, const void *pixels)
Brandon Jones142ec422014-07-16 10:31:30 -07002230{
Brandon Jonescef06ff2014-08-05 13:27:48 -07002231 ASSERT(target == GL_TEXTURE_2D_ARRAY);
2232
Brandon Jones142ec422014-07-16 10:31:30 -07002233 // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
2234 redefineImage(level, format, width, height, depth);
2235
Geoff Lang5d601382014-07-22 15:14:06 -04002236 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
2237 GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
Brandon Jones142ec422014-07-16 10:31:30 -07002238
2239 for (int i = 0; i < depth; i++)
2240 {
2241 const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
Geoff Langb5348332014-09-02 13:16:34 -04002242 gl::Error error = TextureD3D::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]);
2243 if (error.isError())
2244 {
2245 return error;
2246 }
Brandon Jones142ec422014-07-16 10:31:30 -07002247 }
Geoff Langb5348332014-09-02 13:16:34 -04002248
2249 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002250}
2251
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002252gl::Error TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
2253 GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
2254 const gl::PixelUnpackState &unpack, const void *pixels)
Brandon Jones142ec422014-07-16 10:31:30 -07002255{
Brandon Jonescef06ff2014-08-05 13:27:48 -07002256 ASSERT(target == GL_TEXTURE_2D_ARRAY);
2257
Geoff Lang5d601382014-07-22 15:14:06 -04002258 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level));
2259 GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment);
Brandon Jones142ec422014-07-16 10:31:30 -07002260
2261 for (int i = 0; i < depth; i++)
2262 {
2263 int layer = zoffset + i;
2264 const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
2265
Jamie Madillfeda4d22014-09-17 13:03:29 -04002266 gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
Jamie Madille6b6da02014-10-02 11:03:14 -04002267 gl::Error error = TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type,
2268 unpack, layerPixels, index);
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002269 if (error.isError())
2270 {
2271 return error;
Brandon Jones142ec422014-07-16 10:31:30 -07002272 }
2273 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002274
2275 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002276}
2277
Geoff Langb5348332014-09-02 13:16:34 -04002278gl::Error TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
2279 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
2280 GLsizei imageSize, const void *pixels)
Brandon Jones142ec422014-07-16 10:31:30 -07002281{
Brandon Jonescef06ff2014-08-05 13:27:48 -07002282 ASSERT(target == GL_TEXTURE_2D_ARRAY);
2283
Geoff Lang5d601382014-07-22 15:14:06 -04002284 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
2285 GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
Brandon Jones142ec422014-07-16 10:31:30 -07002286
2287 for (int i = 0; i < depth; i++)
2288 {
2289 int layer = zoffset + i;
2290 const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
2291
Geoff Langb5348332014-09-02 13:16:34 -04002292 gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer]);
2293 if (error.isError())
Brandon Jones142ec422014-07-16 10:31:30 -07002294 {
Geoff Langb5348332014-09-02 13:16:34 -04002295 return error;
2296 }
2297
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04002298 gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
2299 gl::Box region(xoffset, yoffset, 0, width, height, 1);
2300 error = commitRegion(index, region);
Geoff Langb5348332014-09-02 13:16:34 -04002301 if (error.isError())
2302 {
2303 return error;
Brandon Jones142ec422014-07-16 10:31:30 -07002304 }
2305 }
Geoff Langb5348332014-09-02 13:16:34 -04002306
2307 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002308}
2309
Geoff Langef7b0162014-09-04 13:29:23 -04002310gl::Error TextureD3D_2DArray::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
Brandon Jonescef06ff2014-08-05 13:27:48 -07002311{
2312 UNIMPLEMENTED();
Geoff Langef7b0162014-09-04 13:29:23 -04002313 return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented.");
Brandon Jonescef06ff2014-08-05 13:27:48 -07002314}
2315
Geoff Langef7b0162014-09-04 13:29:23 -04002316gl::Error TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
Brandon Jones142ec422014-07-16 10:31:30 -07002317{
Brandon Jonescef06ff2014-08-05 13:27:48 -07002318 ASSERT(target == GL_TEXTURE_2D_ARRAY);
2319
Brandon Jones142ec422014-07-16 10:31:30 -07002320 // can only make our texture storage to a render target if level 0 is defined (with a width & height) and
2321 // the current level we're copying to is defined (with appropriate format, width & height)
2322 bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
2323
Jamie Madill82bf0c52014-10-03 11:50:53 -04002324 gl::Rectangle sourceRect(x, y, width, height);
2325
Brandon Jones142ec422014-07-16 10:31:30 -07002326 if (!mImageArray[level][0]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
2327 {
Geoff Langef7b0162014-09-04 13:29:23 -04002328 gl::Error error = mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, sourceRect, source);
2329 if (error.isError())
2330 {
2331 return error;
2332 }
2333
Brandon Jones142ec422014-07-16 10:31:30 -07002334 mDirtyImages = true;
2335 }
2336 else
2337 {
Geoff Langef7b0162014-09-04 13:29:23 -04002338 gl::Error error = ensureRenderTarget();
2339 if (error.isError())
2340 {
2341 return error;
2342 }
Brandon Jones142ec422014-07-16 10:31:30 -07002343
2344 if (isValidLevel(level))
2345 {
Geoff Langef7b0162014-09-04 13:29:23 -04002346 error = updateStorageLevel(level);
2347 if (error.isError())
2348 {
2349 return error;
2350 }
Brandon Jones142ec422014-07-16 10:31:30 -07002351
Geoff Langef7b0162014-09-04 13:29:23 -04002352 error = mRenderer->copyImage2DArray(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format,
2353 xoffset, yoffset, zoffset, mTexStorage, level);
2354 if (error.isError())
2355 {
2356 return error;
2357 }
Brandon Jones142ec422014-07-16 10:31:30 -07002358 }
2359 }
Geoff Langef7b0162014-09-04 13:29:23 -04002360 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002361}
2362
Brandon Jonescef06ff2014-08-05 13:27:48 -07002363void TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
Brandon Jones142ec422014-07-16 10:31:30 -07002364{
Brandon Jonescef06ff2014-08-05 13:27:48 -07002365 ASSERT(target == GL_TEXTURE_2D_ARRAY);
2366
Brandon Jones142ec422014-07-16 10:31:30 -07002367 deleteImages();
2368
2369 for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
2370 {
2371 GLsizei levelWidth = std::max(1, width >> level);
2372 GLsizei levelHeight = std::max(1, height >> level);
2373
2374 mLayerCounts[level] = (level < levels ? depth : 0);
2375
2376 if (mLayerCounts[level] > 0)
2377 {
2378 // Create new images for this level
2379 mImageArray[level] = new ImageD3D*[mLayerCounts[level]];
2380
2381 for (int layer = 0; layer < mLayerCounts[level]; layer++)
2382 {
2383 mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage());
2384 mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, levelWidth,
2385 levelHeight, 1, true);
2386 }
2387 }
2388 }
2389
2390 mImmutable = true;
Jamie Madillc4833262014-09-18 16:18:26 -04002391
2392 bool renderTarget = IsRenderTargetUsage(mUsage);
2393 TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalformat, renderTarget, width, height, depth, levels);
Jamie Madill2f06dbf2014-09-18 15:08:50 -04002394 setCompleteTexStorage(storage);
Brandon Jones142ec422014-07-16 10:31:30 -07002395}
2396
Brandon Jones6053a522014-07-25 16:22:09 -07002397void TextureD3D_2DArray::bindTexImage(egl::Surface *surface)
Brandon Jones142ec422014-07-16 10:31:30 -07002398{
Brandon Jones6053a522014-07-25 16:22:09 -07002399 UNREACHABLE();
Brandon Jones142ec422014-07-16 10:31:30 -07002400}
2401
Brandon Jones6053a522014-07-25 16:22:09 -07002402void TextureD3D_2DArray::releaseTexImage()
Brandon Jones142ec422014-07-16 10:31:30 -07002403{
Brandon Jones6053a522014-07-25 16:22:09 -07002404 UNREACHABLE();
Brandon Jones142ec422014-07-16 10:31:30 -07002405}
2406
Brandon Jones6053a522014-07-25 16:22:09 -07002407
Jamie Madill4aa79e12014-09-29 10:46:14 -04002408void TextureD3D_2DArray::initMipmapsImages()
Brandon Jones142ec422014-07-16 10:31:30 -07002409{
2410 int baseWidth = getBaseLevelWidth();
2411 int baseHeight = getBaseLevelHeight();
2412 int baseDepth = getBaseLevelDepth();
2413 GLenum baseFormat = getBaseLevelInternalFormat();
2414
2415 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
2416 int levelCount = mipLevels();
2417 for (int level = 1; level < levelCount; level++)
2418 {
2419 redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth);
2420 }
Brandon Jones142ec422014-07-16 10:31:30 -07002421}
2422
Jamie Madillac7579c2014-09-17 16:59:33 -04002423unsigned int TextureD3D_2DArray::getRenderTargetSerial(const gl::ImageIndex &index)
Brandon Jones142ec422014-07-16 10:31:30 -07002424{
Geoff Langef7b0162014-09-04 13:29:23 -04002425 return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
Brandon Jones142ec422014-07-16 10:31:30 -07002426}
2427
Jamie Madillac7579c2014-09-17 16:59:33 -04002428RenderTarget *TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index)
Brandon Jones142ec422014-07-16 10:31:30 -07002429{
2430 // ensure the underlying texture is created
Geoff Langef7b0162014-09-04 13:29:23 -04002431 gl::Error error = ensureRenderTarget();
2432 if (error.isError())
Brandon Jones142ec422014-07-16 10:31:30 -07002433 {
2434 return NULL;
2435 }
2436
Geoff Langef7b0162014-09-04 13:29:23 -04002437 error = updateStorageLevel(index.mipIndex);
2438 if (error.isError())
2439 {
2440 return NULL;
2441 }
2442
Jamie Madill2f06dbf2014-09-18 15:08:50 -04002443 return mTexStorage->getRenderTarget(index);
Brandon Jones142ec422014-07-16 10:31:30 -07002444}
2445
Geoff Langef7b0162014-09-04 13:29:23 -04002446gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget)
Brandon Jones142ec422014-07-16 10:31:30 -07002447{
2448 // Only initialize the first time this texture is used as a render target or shader resource
2449 if (mTexStorage)
2450 {
Geoff Langef7b0162014-09-04 13:29:23 -04002451 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002452 }
2453
2454 // do not attempt to create storage for nonexistant data
2455 if (!isLevelComplete(0))
2456 {
Geoff Langef7b0162014-09-04 13:29:23 -04002457 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002458 }
2459
2460 bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
2461
Geoff Langef7b0162014-09-04 13:29:23 -04002462 TextureStorage *storage = NULL;
2463 gl::Error error = createCompleteStorage(createRenderTarget, &storage);
2464 if (error.isError())
2465 {
2466 return error;
2467 }
2468
2469 error = setCompleteTexStorage(storage);
2470 if (error.isError())
2471 {
2472 SafeDelete(storage);
2473 return error;
2474 }
2475
Brandon Jones142ec422014-07-16 10:31:30 -07002476 ASSERT(mTexStorage);
2477
2478 // flush image data to the storage
Geoff Langef7b0162014-09-04 13:29:23 -04002479 error = updateStorage();
2480 if (error.isError())
2481 {
2482 return error;
2483 }
2484
2485 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002486}
2487
Geoff Langef7b0162014-09-04 13:29:23 -04002488gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const
Brandon Jones142ec422014-07-16 10:31:30 -07002489{
2490 GLsizei width = getBaseLevelWidth();
2491 GLsizei height = getBaseLevelHeight();
Jamie Madill3269bcb2014-09-30 16:33:52 -04002492 GLsizei depth = getLayerCount(0);
Jamie Madillc4833262014-09-18 16:18:26 -04002493 GLenum internalFormat = getBaseLevelInternalFormat();
Brandon Jones142ec422014-07-16 10:31:30 -07002494
2495 ASSERT(width > 0 && height > 0 && depth > 0);
2496
2497 // use existing storage level count, when previously specified by TexStorage*D
2498 GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
2499
Geoff Langef7b0162014-09-04 13:29:23 -04002500 // TODO(geofflang): Verify storage creation succeeds
2501 *outStorage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels);
2502
2503 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002504}
2505
Geoff Langef7b0162014-09-04 13:29:23 -04002506gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
Brandon Jones142ec422014-07-16 10:31:30 -07002507{
2508 SafeDelete(mTexStorage);
2509 mTexStorage = newCompleteTexStorage;
2510 mDirtyImages = true;
2511
2512 // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only
2513 ASSERT(!mTexStorage->isManaged());
Geoff Langef7b0162014-09-04 13:29:23 -04002514
2515 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002516}
2517
Geoff Langef7b0162014-09-04 13:29:23 -04002518gl::Error TextureD3D_2DArray::updateStorage()
Brandon Jones142ec422014-07-16 10:31:30 -07002519{
2520 ASSERT(mTexStorage != NULL);
2521 GLint storageLevels = mTexStorage->getLevelCount();
2522 for (int level = 0; level < storageLevels; level++)
2523 {
2524 if (isLevelComplete(level))
2525 {
Geoff Langef7b0162014-09-04 13:29:23 -04002526 gl::Error error = updateStorageLevel(level);
2527 if (error.isError())
2528 {
2529 return error;
2530 }
Brandon Jones142ec422014-07-16 10:31:30 -07002531 }
2532 }
Geoff Langef7b0162014-09-04 13:29:23 -04002533
2534 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002535}
2536
Brandon Jones142ec422014-07-16 10:31:30 -07002537bool TextureD3D_2DArray::isValidLevel(int level) const
2538{
2539 return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
2540}
2541
2542bool TextureD3D_2DArray::isLevelComplete(int level) const
2543{
2544 ASSERT(level >= 0 && level < (int)ArraySize(mImageArray));
2545
2546 if (isImmutable())
2547 {
2548 return true;
2549 }
2550
2551 GLsizei width = getBaseLevelWidth();
2552 GLsizei height = getBaseLevelHeight();
Jamie Madill3269bcb2014-09-30 16:33:52 -04002553 GLsizei layers = getLayerCount(0);
Brandon Jones142ec422014-07-16 10:31:30 -07002554
2555 if (width <= 0 || height <= 0 || layers <= 0)
2556 {
2557 return false;
2558 }
2559
2560 if (level == 0)
2561 {
2562 return true;
2563 }
2564
2565 if (getInternalFormat(level) != getInternalFormat(0))
2566 {
2567 return false;
2568 }
2569
2570 if (getWidth(level) != std::max(1, width >> level))
2571 {
2572 return false;
2573 }
2574
2575 if (getHeight(level) != std::max(1, height >> level))
2576 {
2577 return false;
2578 }
2579
Jamie Madill3269bcb2014-09-30 16:33:52 -04002580 if (getLayerCount(level) != layers)
Brandon Jones142ec422014-07-16 10:31:30 -07002581 {
2582 return false;
2583 }
2584
2585 return true;
2586}
2587
Geoff Langef7b0162014-09-04 13:29:23 -04002588gl::Error TextureD3D_2DArray::updateStorageLevel(int level)
Brandon Jones142ec422014-07-16 10:31:30 -07002589{
2590 ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts));
2591 ASSERT(isLevelComplete(level));
2592
2593 for (int layer = 0; layer < mLayerCounts[level]; layer++)
2594 {
2595 ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL);
2596 if (mImageArray[level][layer]->isDirty())
2597 {
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04002598 gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
2599 gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
Geoff Langef7b0162014-09-04 13:29:23 -04002600 gl::Error error = commitRegion(index, region);
2601 if (error.isError())
2602 {
2603 return error;
2604 }
Brandon Jones142ec422014-07-16 10:31:30 -07002605 }
2606 }
Geoff Langef7b0162014-09-04 13:29:23 -04002607
2608 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002609}
2610
2611void TextureD3D_2DArray::deleteImages()
2612{
2613 for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
2614 {
2615 for (int layer = 0; layer < mLayerCounts[level]; ++layer)
2616 {
2617 delete mImageArray[level][layer];
2618 }
2619 delete[] mImageArray[level];
2620 mImageArray[level] = NULL;
2621 mLayerCounts[level] = 0;
2622 }
2623}
2624
2625void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
2626{
2627 // If there currently is a corresponding storage texture image, it has these parameters
2628 const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
2629 const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
Jamie Madill3269bcb2014-09-30 16:33:52 -04002630 const int storageDepth = getLayerCount(0);
Brandon Jones142ec422014-07-16 10:31:30 -07002631 const GLenum storageFormat = getBaseLevelInternalFormat();
2632
2633 for (int layer = 0; layer < mLayerCounts[level]; layer++)
2634 {
2635 delete mImageArray[level][layer];
2636 }
2637 delete[] mImageArray[level];
2638 mImageArray[level] = NULL;
2639 mLayerCounts[level] = depth;
2640
2641 if (depth > 0)
2642 {
2643 mImageArray[level] = new ImageD3D*[depth]();
2644
2645 for (int layer = 0; layer < mLayerCounts[level]; layer++)
2646 {
2647 mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage());
2648 mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, width, height, 1, false);
2649 }
2650 }
2651
2652 if (mTexStorage)
2653 {
2654 const int storageLevels = mTexStorage->getLevelCount();
2655
2656 if ((level >= storageLevels && storageLevels != 0) ||
2657 width != storageWidth ||
2658 height != storageHeight ||
2659 depth != storageDepth ||
2660 internalformat != storageFormat) // Discard mismatched storage
2661 {
2662 for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
2663 {
2664 for (int layer = 0; layer < mLayerCounts[level]; layer++)
2665 {
2666 mImageArray[level][layer]->markDirty();
2667 }
2668 }
2669
2670 delete mTexStorage;
2671 mTexStorage = NULL;
2672 mDirtyImages = true;
2673 }
2674 }
2675}
2676
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04002677gl::Error TextureD3D_2DArray::commitRegion(const gl::ImageIndex &index, const gl::Box &region)
Brandon Jones142ec422014-07-16 10:31:30 -07002678{
Jamie Madill7cb2b9d2014-10-02 11:03:13 -04002679 ASSERT(index.hasLayer());
2680 GLint level = index.mipIndex;
2681 GLint layerTarget = index.layerIndex;
2682
Jamie Madill3269bcb2014-09-30 16:33:52 -04002683 if (isValidLevel(level) && layerTarget < getLayerCount(level))
Brandon Jones142ec422014-07-16 10:31:30 -07002684 {
2685 ImageD3D *image = mImageArray[level][layerTarget];
Jamie Madill6b51c1a2014-10-06 16:31:21 -04002686 gl::Error error = image->copyToStorage2DArray(mTexStorage, index, region);
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002687 if (error.isError())
Brandon Jones142ec422014-07-16 10:31:30 -07002688 {
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002689 return error;
Brandon Jones142ec422014-07-16 10:31:30 -07002690 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002691
2692 image->markClean();
Brandon Jones142ec422014-07-16 10:31:30 -07002693 }
Geoff Lang1ba6b8d2014-08-28 10:57:31 -04002694
2695 return gl::Error(GL_NO_ERROR);
Brandon Jones142ec422014-07-16 10:31:30 -07002696}
2697
Jamie Madillef4ac5b2014-09-29 10:46:11 -04002698gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const
2699{
2700 return gl::ImageIndexIterator::Make2DArray(0, mTexStorage->getLevelCount(), mLayerCounts);
2701}
2702
Jamie Madillcb83dc12014-09-29 10:46:12 -04002703gl::ImageIndex TextureD3D_2DArray::getImageIndex(GLint mip, GLint layer) const
2704{
2705 return gl::ImageIndex::Make2DArray(mip, layer);
2706}
2707
Brandon Jones78b1acd2014-07-15 15:33:07 -07002708}