blob: 5eda2cf3ec6961af7e4bc20a4a1476cbd3513804 [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
daniel@transgaming.com95a758f2012-07-12 15:17:06 +00002//
Geoff Langcec35902014-04-16 10:52:36 -04003// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com95a758f2012-07-12 15:17:06 +00004// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// Texture.cpp: Implements the gl::Texture class and its derived classes
9// Texture2D and TextureCubeMap. Implements GL texture objects and related
10// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
11
12#include "libGLESv2/Texture.h"
13
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000014#include "libGLESv2/main.h"
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +000015#include "common/mathutil.h"
16#include "common/utilities.h"
shannonwoods@chromium.org4ad58e02013-05-30 00:08:11 +000017#include "libGLESv2/formatutils.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000018#include "libGLESv2/Renderbuffer.h"
19#include "libGLESv2/renderer/Image.h"
20#include "libGLESv2/renderer/Renderer.h"
Brandon Jones6518fe22014-07-08 15:16:52 -070021#include "libGLESv2/renderer/d3d/ImageD3D.h"
22#include "libGLESv2/renderer/d3d/TextureStorage.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000023#include "libEGL/Surface.h"
Jamie Madill1beb1db2013-09-18 14:36:28 -040024#include "libGLESv2/Buffer.h"
Brandon Jonesd38f9262014-06-18 16:26:45 -070025#include "libGLESv2/renderer/BufferImpl.h"
Jamie Madill0e0510f2013-10-10 15:46:23 -040026#include "libGLESv2/renderer/RenderTarget.h"
Brandon Jonesf47bebc2014-07-09 14:28:42 -070027#include "libGLESv2/renderer/TextureImpl.h"
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000028
29namespace gl
30{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000031
Jamie Madillf8989902013-07-19 16:36:58 -040032bool IsMipmapFiltered(const SamplerState &samplerState)
33{
34 switch (samplerState.minFilter)
35 {
36 case GL_NEAREST:
37 case GL_LINEAR:
38 return false;
39 case GL_NEAREST_MIPMAP_NEAREST:
40 case GL_LINEAR_MIPMAP_NEAREST:
41 case GL_NEAREST_MIPMAP_LINEAR:
42 case GL_LINEAR_MIPMAP_LINEAR:
43 return true;
44 default: UNREACHABLE();
45 return false;
46 }
47}
48
Jamie Madilld4589c92013-10-24 17:49:34 -040049bool IsRenderTargetUsage(GLenum usage)
50{
51 return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
52}
53
Brandon Jonesf47bebc2014-07-09 14:28:42 -070054Texture::Texture(GLuint id, GLenum target)
55 : RefCountObject(id),
56 mUsage(GL_NONE),
57 mImmutable(false),
58 mTarget(target)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000059{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000060}
61
62Texture::~Texture()
63{
64}
65
Geoff Lang4907f2c2013-07-25 12:53:57 -040066GLenum Texture::getTarget() const
67{
68 return mTarget;
69}
70
Geoff Lang63b5f1f2013-09-23 14:52:14 -040071void Texture::setUsage(GLenum usage)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000072{
Geoff Lang63b5f1f2013-09-23 14:52:14 -040073 mUsage = usage;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000074}
75
Brandon Jonesa328d562014-07-01 13:52:40 -070076void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler)
daniel@transgaming.comebf139f2012-10-31 18:07:32 +000077{
78 *sampler = mSamplerState;
Nicolas Capens8de68282014-04-04 11:10:27 -040079
80 // Offset the effective base level by the texture storage's top level
81 rx::TextureStorageInterface *texture = getNativeTexture();
82 int topLevel = texture ? texture->getTopLevel() : 0;
83 sampler->baseLevel = topLevel + mSamplerState.baseLevel;
daniel@transgaming.com07ab8412012-07-12 15:17:09 +000084}
85
daniel@transgaming.com95a758f2012-07-12 15:17:06 +000086GLenum Texture::getUsage() const
87{
88 return mUsage;
89}
90
Jamie Madilld3d2a342013-10-07 10:46:35 -040091GLint Texture::getBaseLevelWidth() const
92{
93 const rx::Image *baseImage = getBaseLevelImage();
94 return (baseImage ? baseImage->getWidth() : 0);
95}
96
97GLint Texture::getBaseLevelHeight() const
98{
99 const rx::Image *baseImage = getBaseLevelImage();
100 return (baseImage ? baseImage->getHeight() : 0);
101}
102
103GLint Texture::getBaseLevelDepth() const
104{
105 const rx::Image *baseImage = getBaseLevelImage();
106 return (baseImage ? baseImage->getDepth() : 0);
107}
108
Jamie Madillb8f8b892014-01-07 10:12:50 -0500109// Note: "base level image" is loosely defined to be any image from the base level,
110// where in the base of 2D array textures and cube maps there are several. Don't use
111// the base level image for anything except querying texture format and size.
Jamie Madilld3d2a342013-10-07 10:46:35 -0400112GLenum Texture::getBaseLevelInternalFormat() const
113{
114 const rx::Image *baseImage = getBaseLevelImage();
115 return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
116}
117
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700118unsigned int Texture::getTextureSerial()
119{
120 rx::TextureStorageInterface *texture = getNativeTexture();
121 return texture ? texture->getTextureSerial() : 0;
122}
123
124bool Texture::isImmutable() const
125{
126 return mImmutable;
127}
128
129int Texture::immutableLevelCount()
130{
131 return (mImmutable ? getNativeTexture()->getStorageInstance()->getLevelCount() : 0);
132}
133
134int Texture::mipLevels() const
135{
136 return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
137}
138
139TextureWithRenderer::TextureWithRenderer(rx::Renderer *renderer, GLuint id, GLenum target)
140 : Texture(id, target),
141 mRenderer(renderer),
142 mDirtyImages(true)
143{
144}
145
146TextureWithRenderer::~TextureWithRenderer()
147{
148}
149
150// TODO: This is only used by the D3D backends and FramebufferAttachment. Once
151// FramebufferAttachment has been refactored this function should be pushed
152// down to TextureD3D.
153rx::TextureStorageInterface *TextureWithRenderer::getNativeTexture()
154{
155 // ensure the underlying texture is created
156 initializeStorage(false);
157
158 rx::TextureStorageInterface *storage = getBaseLevelStorage();
159 if (storage)
160 {
161 updateStorage();
162 }
163
164 return storage;
165}
166
167bool TextureWithRenderer::hasDirtyImages() const
168{
169 return mDirtyImages;
170}
171
172void TextureWithRenderer::resetDirty()
173{
174 mDirtyImages = false;
175}
176
177void TextureWithRenderer::setImage(const PixelUnpackState &unpack, GLenum type, const void *pixels, rx::Image *image)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000178{
Jamie Madillc30003d2014-01-10 12:51:23 -0500179 // No-op
180 if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
181 {
182 return;
183 }
184
Jamie Madillabef6802013-09-05 16:54:19 -0400185 // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
186 // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
Jamie Madill1beb1db2013-09-18 14:36:28 -0400187 const void *pixelData = pixels;
188
189 if (unpack.pixelBuffer.id() != 0)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000190 {
Jamie Madill1beb1db2013-09-18 14:36:28 -0400191 // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported
192 Buffer *pixelBuffer = unpack.pixelBuffer.get();
193 ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
Brandon Jonesd38f9262014-06-18 16:26:45 -0700194 // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data.
195 // This functionality should be moved into renderer and the getData method of BufferImpl removed.
196 const void *bufferData = pixelBuffer->getImplementation()->getData();
Jamie Madill1beb1db2013-09-18 14:36:28 -0400197 pixelData = static_cast<const unsigned char *>(bufferData) + offset;
198 }
199
200 if (pixelData != NULL)
201 {
202 image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000203 mDirtyImages = true;
204 }
205}
206
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700207bool TextureWithRenderer::isFastUnpackable(const PixelUnpackState &unpack, GLenum sizedInternalFormat)
Jamie Madill8cc7d972013-10-10 15:51:55 -0400208{
209 return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
210}
211
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700212bool TextureWithRenderer::fastUnpackPixels(const PixelUnpackState &unpack, const void *pixels, const Box &destArea,
Jamie Madill8cc7d972013-10-10 15:51:55 -0400213 GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget)
Jamie Madill1beb1db2013-09-18 14:36:28 -0400214{
215 if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
216 {
217 return true;
218 }
219
220 // In order to perform the fast copy through the shader, we must have the right format, and be able
221 // to create a render target.
Jamie Madill8cc7d972013-10-10 15:51:55 -0400222 ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat));
Jamie Madill1beb1db2013-09-18 14:36:28 -0400223
Jamie Madill8cc7d972013-10-10 15:51:55 -0400224 unsigned int offset = reinterpret_cast<unsigned int>(pixels);
Jamie Madill1beb1db2013-09-18 14:36:28 -0400225
Jamie Madill8cc7d972013-10-10 15:51:55 -0400226 return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
Jamie Madill1beb1db2013-09-18 14:36:28 -0400227}
228
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700229void TextureWithRenderer::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000230{
231 if (pixels != NULL)
232 {
shannon.woods%transgaming.com@gtempaccount.com4760c562013-04-13 03:42:30 +0000233 image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000234 mDirtyImages = true;
235 }
236}
237
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700238bool TextureWithRenderer::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
Jamie Madill88f18f42013-09-18 14:36:19 -0400239 GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels, rx::Image *image)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000240{
Jamie Madill065e1a32013-10-10 15:11:50 -0400241 const void *pixelData = pixels;
242
243 // CPU readback & copy where direct GPU copy is not supported
244 if (unpack.pixelBuffer.id() != 0)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000245 {
Jamie Madill065e1a32013-10-10 15:11:50 -0400246 Buffer *pixelBuffer = unpack.pixelBuffer.get();
247 unsigned int offset = reinterpret_cast<unsigned int>(pixels);
Brandon Jonesd38f9262014-06-18 16:26:45 -0700248 // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data.
249 // This functionality should be moved into renderer and the getData method of BufferImpl removed.
250 const void *bufferData = pixelBuffer->getImplementation()->getData();
Jamie Madill065e1a32013-10-10 15:11:50 -0400251 pixelData = static_cast<const unsigned char *>(bufferData) + offset;
252 }
253
254 if (pixelData != NULL)
255 {
256 image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, type, pixelData);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000257 mDirtyImages = true;
258 }
259
260 return true;
261}
262
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700263bool TextureWithRenderer::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
shannon.woods%transgaming.com@gtempaccount.com4760c562013-04-13 03:42:30 +0000264 GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000265{
266 if (pixels != NULL)
267 {
shannon.woods%transgaming.com@gtempaccount.com4760c562013-04-13 03:42:30 +0000268 image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000269 mDirtyImages = true;
270 }
271
272 return true;
273}
274
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700275GLint TextureWithRenderer::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000276{
Geoff Langc0b9ef42014-07-02 10:02:37 -0400277 // TODO(geofflang): use context's extensions
278 if ((isPow2(width) && isPow2(height) && isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000279 {
Jamie Madill6b7440c2013-10-24 17:49:47 -0400280 // Maximum number of levels
Geoff Lang98705b72014-03-31 16:00:03 -0400281 return log2(std::max(std::max(width, height), depth)) + 1;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000282 }
283 else
284 {
285 // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
286 return 1;
287 }
288}
289
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700290Texture2D::Texture2D(rx::Texture2DImpl *impl, GLuint id)
291 : Texture(id, GL_TEXTURE_2D),
292 mTexture(impl)
Jamie Madill22f843a2013-10-24 17:49:36 -0400293{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000294 mSurface = NULL;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000295}
296
297Texture2D::~Texture2D()
298{
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700299 SafeDelete(mTexture);
300
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000301 if (mSurface)
302 {
303 mSurface->setBoundTexture(NULL);
304 mSurface = NULL;
305 }
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700306}
daniel@transgaming.comd9ec9022012-12-20 20:52:16 +0000307
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700308rx::TextureStorageInterface *Texture2D::getNativeTexture()
309{
310 return mTexture->getNativeTexture();
311}
312
313void Texture2D::setUsage(GLenum usage)
314{
315 mUsage = usage;
316 mTexture->setUsage(usage);
317}
318
319bool Texture2D::hasDirtyImages() const
320{
321 return mTexture->hasDirtyImages();
322}
323
324void Texture2D::resetDirty()
325{
326 mTexture->resetDirty();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000327}
328
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000329GLsizei Texture2D::getWidth(GLint level) const
330{
331 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700332 return mTexture->getImage(level)->getWidth();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000333 else
334 return 0;
335}
336
337GLsizei Texture2D::getHeight(GLint level) const
338{
339 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700340 return mTexture->getImage(level)->getHeight();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000341 else
342 return 0;
343}
344
345GLenum Texture2D::getInternalFormat(GLint level) const
346{
347 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700348 return mTexture->getImage(level)->getInternalFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000349 else
350 return GL_NONE;
351}
352
daniel@transgaming.com20d36662012-10-31 19:51:43 +0000353GLenum Texture2D::getActualFormat(GLint level) const
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000354{
355 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700356 return mTexture->getImage(level)->getActualFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000357 else
Geoff Langcbf727a2014-02-10 12:50:45 -0500358 return GL_NONE;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000359}
360
Geoff Lang005df412013-10-16 14:12:50 -0400361void Texture2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000362{
363 releaseTexImage();
shannon.woods@transgaming.com8a406682013-02-28 23:15:26 +0000364
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700365 mTexture->redefineImage(level, internalformat, width, height);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000366}
367
Geoff Lang005df412013-10-16 14:12:50 -0400368void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000369{
Geoff Lange4a492b2014-06-19 14:14:41 -0400370 GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat) ? internalFormat
371 : GetSizedInternalFormat(format, type);
shannonwoods@chromium.org4ad58e02013-05-30 00:08:11 +0000372 redefineImage(level, sizedInternalFormat, width, height);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000373
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700374 mTexture->setImage(level, width, height, internalFormat, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000375}
376
377void Texture2D::bindTexImage(egl::Surface *surface)
378{
379 releaseTexImage();
380
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700381 mTexture->bindTexImage(surface);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000382
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000383 mSurface = surface;
384 mSurface->setBoundTexture(this);
385}
386
387void Texture2D::releaseTexImage()
388{
389 if (mSurface)
390 {
391 mSurface->setBoundTexture(NULL);
392 mSurface = NULL;
393
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700394 mTexture->releaseTexImage();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000395 }
396}
397
398void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
399{
daniel@transgaming.com6452adf2012-10-17 18:22:35 +0000400 // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
shannon.woods@transgaming.come2e97982013-02-28 23:18:50 +0000401 redefineImage(level, format, width, height);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000402
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700403 mTexture->setCompressedImage(level, format, width, height, imageSize, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000404}
405
Jamie Madill88f18f42013-09-18 14:36:19 -0400406void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000407{
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700408 mTexture->subImage(level, xoffset, yoffset, width, height, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000409}
410
411void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
412{
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700413 mTexture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000414}
415
416void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
417{
Geoff Lange4a492b2014-06-19 14:14:41 -0400418 GLenum sizedInternalFormat = IsSizedInternalFormat(format) ? format
419 : GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
shannonwoods@chromium.org557aab02013-05-30 00:08:27 +0000420 redefineImage(level, sizedInternalFormat, width, height);
shannon.woods@transgaming.com8a406682013-02-28 23:15:26 +0000421
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700422 mTexture->copyImage(level, format, x, y, width, height, source);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000423}
424
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000425void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000426{
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700427 mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000428}
429
430void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
431{
Jamie Madill73b5d062013-10-24 17:49:38 -0400432 mImmutable = true;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000433
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700434 mTexture->storage(levels, internalformat, width, height);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000435}
436
437// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
Jamie Madillf8989902013-07-19 16:36:58 -0400438bool Texture2D::isSamplerComplete(const SamplerState &samplerState) const
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000439{
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700440 return mTexture->isSamplerComplete(samplerState);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000441}
442
443bool Texture2D::isCompressed(GLint level) const
444{
Geoff Lange4a492b2014-06-19 14:14:41 -0400445 return IsFormatCompressed(getInternalFormat(level));
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000446}
447
448bool Texture2D::isDepth(GLint level) const
449{
Geoff Lange4a492b2014-06-19 14:14:41 -0400450 return GetDepthBits(getInternalFormat(level)) > 0;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000451}
452
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000453void Texture2D::generateMipmaps()
454{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000455 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
Geoff Lang98705b72014-03-31 16:00:03 -0400456 int levelCount = mipLevels();
457 for (int level = 1; level < levelCount; level++)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000458 {
Jamie Madill22f843a2013-10-24 17:49:36 -0400459 redefineImage(level, getBaseLevelInternalFormat(),
460 std::max(getBaseLevelWidth() >> level, 1),
461 std::max(getBaseLevelHeight() >> level, 1));
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000462 }
463
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700464 mTexture->generateMipmaps();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000465}
466
Jamie Madilld3d2a342013-10-07 10:46:35 -0400467const rx::Image *Texture2D::getBaseLevelImage() const
468{
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700469 return mTexture->getImage(0);
Jamie Madill2ebab852013-10-24 17:49:42 -0400470}
471
Geoff Lang8040f572013-07-25 16:49:54 -0400472unsigned int Texture2D::getRenderTargetSerial(GLint level)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000473{
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700474 return mTexture->getRenderTargetSerial(level);
Geoff Lang8040f572013-07-25 16:49:54 -0400475}
476
477rx::RenderTarget *Texture2D::getRenderTarget(GLint level)
478{
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700479 return mTexture->getRenderTarget(level);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000480}
481
Geoff Lang8040f572013-07-25 16:49:54 -0400482rx::RenderTarget *Texture2D::getDepthSencil(GLint level)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000483{
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700484 return mTexture->getDepthSencil(level);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000485}
486
Brandon Jones0511e802014-07-14 16:27:26 -0700487TextureCubeMap::TextureCubeMap(rx::TextureCubeImpl *impl, GLuint id)
488 : Texture(id, GL_TEXTURE_CUBE_MAP),
489 mTexture(impl)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000490{
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000491}
492
493TextureCubeMap::~TextureCubeMap()
494{
Brandon Jones0511e802014-07-14 16:27:26 -0700495 SafeDelete(mTexture);
496}
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000497
Brandon Jones0511e802014-07-14 16:27:26 -0700498rx::TextureStorageInterface *TextureCubeMap::getNativeTexture()
499{
500 return mTexture->getNativeTexture();
501}
502
503void TextureCubeMap::setUsage(GLenum usage)
504{
505 mUsage = usage;
506 mTexture->setUsage(usage);
507}
508
509bool TextureCubeMap::hasDirtyImages() const
510{
511 return mTexture->hasDirtyImages();
512}
513
514void TextureCubeMap::resetDirty()
515{
516 mTexture->resetDirty();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000517}
518
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000519GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
520{
521 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jones0511e802014-07-14 16:27:26 -0700522 return mTexture->getImage(target, level)->getWidth();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000523 else
524 return 0;
525}
526
527GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
528{
529 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jones0511e802014-07-14 16:27:26 -0700530 return mTexture->getImage(target, level)->getHeight();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000531 else
532 return 0;
533}
534
535GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
536{
537 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jones0511e802014-07-14 16:27:26 -0700538 return mTexture->getImage(target, level)->getInternalFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000539 else
540 return GL_NONE;
541}
542
daniel@transgaming.com20d36662012-10-31 19:51:43 +0000543GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000544{
545 if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Brandon Jones0511e802014-07-14 16:27:26 -0700546 return mTexture->getImage(target, level)->getActualFormat();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000547 else
Geoff Langcbf727a2014-02-10 12:50:45 -0500548 return GL_NONE;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000549}
550
Geoff Lang005df412013-10-16 14:12:50 -0400551void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000552{
Brandon Jones0511e802014-07-14 16:27:26 -0700553 mTexture->setImage(0, level, width, height, internalFormat, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000554}
555
Geoff Lang005df412013-10-16 14:12:50 -0400556void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000557{
Brandon Jones0511e802014-07-14 16:27:26 -0700558 mTexture->setImage(1, level, width, height, internalFormat, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000559}
560
Geoff Lang005df412013-10-16 14:12:50 -0400561void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000562{
Brandon Jones0511e802014-07-14 16:27:26 -0700563 mTexture->setImage(2, level, width, height, internalFormat, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000564}
565
Geoff Lang005df412013-10-16 14:12:50 -0400566void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000567{
Brandon Jones0511e802014-07-14 16:27:26 -0700568 mTexture->setImage(3, level, width, height, internalFormat, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000569}
570
Geoff Lang005df412013-10-16 14:12:50 -0400571void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000572{
Brandon Jones0511e802014-07-14 16:27:26 -0700573 mTexture->setImage(4, level, width, height, internalFormat, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000574}
575
Geoff Lang005df412013-10-16 14:12:50 -0400576void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000577{
Brandon Jones0511e802014-07-14 16:27:26 -0700578 mTexture->setImage(5, level, width, height, internalFormat, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000579}
580
Jamie Madill2db197c2013-10-24 17:49:35 -0400581void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000582{
Brandon Jones0511e802014-07-14 16:27:26 -0700583 mTexture->setCompressedImage(target, level, format, width, height, imageSize, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000584}
585
Jamie Madill88f18f42013-09-18 14:36:19 -0400586void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000587{
Brandon Jones0511e802014-07-14 16:27:26 -0700588 mTexture->subImage(target, level, xoffset, yoffset, width, height, format, type, unpack, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000589}
590
591void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
592{
Brandon Jones0511e802014-07-14 16:27:26 -0700593 mTexture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, pixels);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000594}
595
596// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86.
Jamie Madillf8989902013-07-19 16:36:58 -0400597bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState) const
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000598{
Brandon Jones0511e802014-07-14 16:27:26 -0700599 return mTexture->isSamplerComplete(samplerState);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000600}
601
602// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
603bool TextureCubeMap::isCubeComplete() const
604{
Brandon Jones0511e802014-07-14 16:27:26 -0700605 return mTexture->isCubeComplete();
Jamie Madill07edd442013-07-19 16:36:58 -0400606}
607
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000608bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
609{
Geoff Lange4a492b2014-06-19 14:14:41 -0400610 return IsFormatCompressed(getInternalFormat(target, level));
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000611}
612
Geoff Lang8040f572013-07-25 16:49:54 -0400613bool TextureCubeMap::isDepth(GLenum target, GLint level) const
614{
Geoff Lange4a492b2014-06-19 14:14:41 -0400615 return GetDepthBits(getInternalFormat(target, level)) > 0;
Geoff Lang8040f572013-07-25 16:49:54 -0400616}
617
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000618void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
619{
Brandon Jones0511e802014-07-14 16:27:26 -0700620 mTexture->copyImage(target, level, format, x, y, width, height, source);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000621}
622
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000623void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000624{
Brandon Jones0511e802014-07-14 16:27:26 -0700625 mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000626}
627
628void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
629{
Jamie Madill3c0989c2013-10-24 17:49:39 -0400630 mImmutable = true;
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000631
Brandon Jones0511e802014-07-14 16:27:26 -0700632 mTexture->storage(levels, internalformat, size);
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000633}
634
635void TextureCubeMap::generateMipmaps()
636{
Brandon Jones0511e802014-07-14 16:27:26 -0700637 mTexture->generateMipmaps();
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000638}
639
Jamie Madilld3d2a342013-10-07 10:46:35 -0400640const rx::Image *TextureCubeMap::getBaseLevelImage() const
641{
642 // Note: if we are not cube-complete, there is no single base level image that can describe all
643 // cube faces, so this method is only well-defined for a cube-complete base level.
Brandon Jones0511e802014-07-14 16:27:26 -0700644 return mTexture->getImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
Jamie Madill2ebab852013-10-24 17:49:42 -0400645}
646
Jamie Madill2db197c2013-10-24 17:49:35 -0400647unsigned int TextureCubeMap::getRenderTargetSerial(GLenum target, GLint level)
Geoff Lang8040f572013-07-25 16:49:54 -0400648{
Brandon Jones0511e802014-07-14 16:27:26 -0700649 return mTexture->getRenderTargetSerial(target, level);
Geoff Lang8040f572013-07-25 16:49:54 -0400650}
651
652rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target, GLint level)
daniel@transgaming.com95a758f2012-07-12 15:17:06 +0000653{
Brandon Jones0511e802014-07-14 16:27:26 -0700654 return mTexture->getRenderTarget(target, level);
Geoff Lang8040f572013-07-25 16:49:54 -0400655}
656
657rx::RenderTarget *TextureCubeMap::getDepthStencil(GLenum target, GLint level)
658{
Brandon Jones0511e802014-07-14 16:27:26 -0700659 return mTexture->getDepthStencil(target, level);
daniel@transgaming.com690d8ae2012-10-31 19:52:08 +0000660}
661
Brandon Jones78b1acd2014-07-15 15:33:07 -0700662Texture3D::Texture3D(rx::Texture3DImpl *impl, GLuint id)
663 : Texture(id, GL_TEXTURE_3D),
664 mTexture(impl)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000665{
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000666}
667
668Texture3D::~Texture3D()
669{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700670 SafeDelete(mTexture);
671}
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000672
Brandon Jones78b1acd2014-07-15 15:33:07 -0700673rx::TextureStorageInterface *Texture3D::getNativeTexture()
674{
675 return mTexture->getNativeTexture();
676}
677
678void Texture3D::setUsage(GLenum usage)
679{
680 mUsage = usage;
681 mTexture->setUsage(usage);
682}
683
684bool Texture3D::hasDirtyImages() const
685{
686 return mTexture->hasDirtyImages();
687}
688
689void Texture3D::resetDirty()
690{
691 mTexture->resetDirty();
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000692}
693
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000694GLsizei Texture3D::getWidth(GLint level) const
695{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700696 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getWidth() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000697}
698
699GLsizei Texture3D::getHeight(GLint level) const
700{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700701 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getHeight() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000702}
703
704GLsizei Texture3D::getDepth(GLint level) const
705{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700706 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getDepth() : 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000707}
708
709GLenum Texture3D::getInternalFormat(GLint level) const
710{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700711 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getInternalFormat() : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000712}
713
714GLenum Texture3D::getActualFormat(GLint level) const
715{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700716 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getActualFormat() : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000717}
718
719bool Texture3D::isCompressed(GLint level) const
720{
Geoff Lange4a492b2014-06-19 14:14:41 -0400721 return IsFormatCompressed(getInternalFormat(level));
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000722}
723
724bool Texture3D::isDepth(GLint level) const
725{
Geoff Lange4a492b2014-06-19 14:14:41 -0400726 return GetDepthBits(getInternalFormat(level)) > 0;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000727}
728
Geoff Lang005df412013-10-16 14:12:50 -0400729void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000730{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700731 mTexture->setImage(level, width, height, depth, internalFormat, format, type, unpack, pixels);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000732}
733
734void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
735{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700736 mTexture->setCompressedImage(level, format, width, height, depth, imageSize, pixels);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000737}
738
Jamie Madill88f18f42013-09-18 14:36:19 -0400739void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000740{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700741 mTexture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000742}
743
744void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
745{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700746 mTexture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000747}
748
749void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
750{
Jamie Madille664e202013-10-24 17:49:40 -0400751 mImmutable = true;
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000752
Brandon Jones78b1acd2014-07-15 15:33:07 -0700753 mTexture->storage(levels, internalformat, width, height, depth);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000754}
755
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000756void Texture3D::generateMipmaps()
757{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700758 mTexture->generateMipmaps();
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000759}
760
Jamie Madilld3d2a342013-10-07 10:46:35 -0400761const rx::Image *Texture3D::getBaseLevelImage() const
762{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700763 return mTexture->getImage(0);
Jamie Madill2ebab852013-10-24 17:49:42 -0400764}
765
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000766void Texture3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
767{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700768 mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000769}
770
Jamie Madillf8989902013-07-19 16:36:58 -0400771bool Texture3D::isSamplerComplete(const SamplerState &samplerState) const
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000772{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700773 return mTexture->isSamplerComplete(samplerState);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000774}
775
776bool Texture3D::isMipmapComplete() const
777{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700778 return mTexture->isMipmapComplete();
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000779}
780
Geoff Lang8040f572013-07-25 16:49:54 -0400781unsigned int Texture3D::getRenderTargetSerial(GLint level, GLint layer)
782{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700783 return mTexture->getRenderTargetSerial(level, layer);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000784}
785
Jamie Madilla2d4e552013-10-10 15:12:01 -0400786rx::RenderTarget *Texture3D::getRenderTarget(GLint level)
787{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700788 return mTexture->getRenderTarget(level);
Jamie Madilla2d4e552013-10-10 15:12:01 -0400789}
790
Geoff Lang8040f572013-07-25 16:49:54 -0400791rx::RenderTarget *Texture3D::getRenderTarget(GLint level, GLint layer)
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000792{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700793 return mTexture->getRenderTarget(level, layer);
Geoff Lang8040f572013-07-25 16:49:54 -0400794}
795
796rx::RenderTarget *Texture3D::getDepthStencil(GLint level, GLint layer)
797{
Brandon Jones78b1acd2014-07-15 15:33:07 -0700798 return mTexture->getDepthStencil(level, layer);
shannon.woods%transgaming.com@gtempaccount.com95996562013-04-13 03:44:58 +0000799}
800
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700801Texture2DArray::Texture2DArray(rx::Renderer *renderer, GLuint id)
802 : TextureWithRenderer(renderer, id, GL_TEXTURE_2D_ARRAY)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000803{
804 mTexStorage = NULL;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000805
806 for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
807 {
808 mLayerCounts[level] = 0;
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000809 mImageArray[level] = NULL;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000810 }
811}
812
813Texture2DArray::~Texture2DArray()
814{
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000815 delete mTexStorage;
816 mTexStorage = NULL;
Jamie Madill884a4622013-10-24 17:49:41 -0400817
818 deleteImages();
819}
820
821void Texture2DArray::deleteImages()
822{
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000823 for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
824 {
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000825 for (int layer = 0; layer < mLayerCounts[level]; ++layer)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000826 {
827 delete mImageArray[level][layer];
828 }
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000829 delete[] mImageArray[level];
Jamie Madill884a4622013-10-24 17:49:41 -0400830 mImageArray[level] = NULL;
831 mLayerCounts[level] = 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000832 }
833}
834
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000835GLsizei Texture2DArray::getWidth(GLint level) const
836{
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000837 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getWidth() : 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000838}
839
840GLsizei Texture2DArray::getHeight(GLint level) const
841{
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000842 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000843}
844
Jamie Madillb8f8b892014-01-07 10:12:50 -0500845GLsizei Texture2DArray::getLayers(GLint level) const
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000846{
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000847 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mLayerCounts[level] : 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000848}
849
850GLenum Texture2DArray::getInternalFormat(GLint level) const
851{
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000852 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000853}
854
855GLenum Texture2DArray::getActualFormat(GLint level) const
856{
Geoff Langcbf727a2014-02-10 12:50:45 -0500857 return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getActualFormat() : GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000858}
859
860bool Texture2DArray::isCompressed(GLint level) const
861{
Geoff Lange4a492b2014-06-19 14:14:41 -0400862 return IsFormatCompressed(getInternalFormat(level));
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000863}
864
865bool Texture2DArray::isDepth(GLint level) const
866{
Geoff Lange4a492b2014-06-19 14:14:41 -0400867 return GetDepthBits(getInternalFormat(level)) > 0;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000868}
869
Geoff Lang005df412013-10-16 14:12:50 -0400870void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000871{
Geoff Lange4a492b2014-06-19 14:14:41 -0400872 GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat) ? internalFormat
873 : GetSizedInternalFormat(format, type);
shannonwoods@chromium.org4ad58e02013-05-30 00:08:11 +0000874 redefineImage(level, sizedInternalFormat, width, height, depth);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000875
Geoff Lange4a492b2014-06-19 14:14:41 -0400876 GLsizei inputDepthPitch = gl::GetDepthPitch(sizedInternalFormat, type, width, height, unpack.alignment);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000877
878 for (int i = 0; i < depth; i++)
879 {
Geoff Lang0bbd11c2013-08-21 14:42:01 -0400880 const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700881 TextureWithRenderer::setImage(unpack, type, layerPixels, mImageArray[level][i]);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000882 }
883}
884
885void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
886{
887 // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
888 redefineImage(level, format, width, height, depth);
889
Geoff Lange4a492b2014-06-19 14:14:41 -0400890 GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, width, height, 1);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000891
892 for (int i = 0; i < depth; i++)
893 {
Geoff Lang0bbd11c2013-08-21 14:42:01 -0400894 const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700895 TextureWithRenderer::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000896 }
897}
898
Jamie Madill88f18f42013-09-18 14:36:19 -0400899void Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000900{
Geoff Lang005df412013-10-16 14:12:50 -0400901 GLenum internalformat = getInternalFormat(level);
Geoff Lange4a492b2014-06-19 14:14:41 -0400902 GLsizei inputDepthPitch = gl::GetDepthPitch(internalformat, type, width, height, unpack.alignment);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000903
904 for (int i = 0; i < depth; i++)
905 {
906 int layer = zoffset + i;
Geoff Lang0bbd11c2013-08-21 14:42:01 -0400907 const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000908
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700909 if (TextureWithRenderer::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, mImageArray[level][layer]))
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000910 {
911 commitRect(level, xoffset, yoffset, layer, width, height);
912 }
913 }
914}
915
916void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
917{
Geoff Lange4a492b2014-06-19 14:14:41 -0400918 GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, width, height, 1);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000919
920 for (int i = 0; i < depth; i++)
921 {
922 int layer = zoffset + i;
Geoff Lang0bbd11c2013-08-21 14:42:01 -0400923 const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000924
Brandon Jonesf47bebc2014-07-09 14:28:42 -0700925 if (TextureWithRenderer::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer]))
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000926 {
927 commitRect(level, xoffset, yoffset, layer, width, height);
928 }
929 }
930}
931
932void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
933{
Jamie Madill884a4622013-10-24 17:49:41 -0400934 deleteImages();
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000935
936 for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
937 {
Jamie Madill884a4622013-10-24 17:49:41 -0400938 GLsizei levelWidth = std::max(1, width >> level);
939 GLsizei levelHeight = std::max(1, height >> level);
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000940
Jamie Madill884a4622013-10-24 17:49:41 -0400941 mLayerCounts[level] = (level < levels ? depth : 0);
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000942
Jamie Madill884a4622013-10-24 17:49:41 -0400943 if (mLayerCounts[level] > 0)
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000944 {
945 // Create new images for this level
Jamie Madill884a4622013-10-24 17:49:41 -0400946 mImageArray[level] = new rx::Image*[mLayerCounts[level]];
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000947
948 for (int layer = 0; layer < mLayerCounts[level]; layer++)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000949 {
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +0000950 mImageArray[level][layer] = mRenderer->createImage();
951 mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, levelWidth,
952 levelHeight, 1, true);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000953 }
954 }
955 }
956
Jamie Madill884a4622013-10-24 17:49:41 -0400957 mImmutable = true;
Nicolas Capensbf712d02014-03-31 14:23:35 -0400958 setCompleteTexStorage(new rx::TextureStorageInterface2DArray(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels));
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000959}
960
961void Texture2DArray::generateMipmaps()
962{
Jamie Madilld3d2a342013-10-07 10:46:35 -0400963 int baseWidth = getBaseLevelWidth();
964 int baseHeight = getBaseLevelHeight();
965 int baseDepth = getBaseLevelDepth();
966 GLenum baseFormat = getBaseLevelInternalFormat();
967
shannonwoods@chromium.org30aa1a92013-05-30 00:03:13 +0000968 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
Geoff Lang98705b72014-03-31 16:00:03 -0400969 int levelCount = mipLevels();
970 for (int level = 1; level < levelCount; level++)
shannonwoods@chromium.org30aa1a92013-05-30 00:03:13 +0000971 {
Jamie Madill22f843a2013-10-24 17:49:36 -0400972 redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth);
shannonwoods@chromium.org30aa1a92013-05-30 00:03:13 +0000973 }
974
975 if (mTexStorage && mTexStorage->isRenderTarget())
976 {
Geoff Lang98705b72014-03-31 16:00:03 -0400977 for (int level = 1; level < levelCount; level++)
shannonwoods@chromium.org30aa1a92013-05-30 00:03:13 +0000978 {
979 mTexStorage->generateMipmap(level);
980
981 for (int layer = 0; layer < mLayerCounts[level]; layer++)
982 {
983 mImageArray[level][layer]->markClean();
984 }
985 }
986 }
987 else
988 {
Geoff Lang98705b72014-03-31 16:00:03 -0400989 for (int level = 1; level < levelCount; level++)
shannonwoods@chromium.org30aa1a92013-05-30 00:03:13 +0000990 {
991 for (int layer = 0; layer < mLayerCounts[level]; layer++)
992 {
993 mRenderer->generateMipmap(mImageArray[level][layer], mImageArray[level - 1][layer]);
994 }
995 }
996 }
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +0000997}
998
Jamie Madilld3d2a342013-10-07 10:46:35 -0400999const rx::Image *Texture2DArray::getBaseLevelImage() const
1000{
Jamie Madill152ed092013-10-09 17:01:15 -04001001 return (mLayerCounts[0] > 0 ? mImageArray[0][0] : NULL);
Jamie Madilld3d2a342013-10-07 10:46:35 -04001002}
1003
Jamie Madill2ebab852013-10-24 17:49:42 -04001004rx::TextureStorageInterface *Texture2DArray::getBaseLevelStorage()
1005{
1006 return mTexStorage;
1007}
1008
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001009void Texture2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
1010{
Jamie Madill07edd442013-07-19 16:36:58 -04001011 // can only make our texture storage to a render target if level 0 is defined (with a width & height) and
1012 // the current level we're copying to is defined (with appropriate format, width & height)
1013 bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
1014
1015 if (!mImageArray[level][0]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001016 {
1017 mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, x, y, width, height, source);
1018 mDirtyImages = true;
1019 }
1020 else
1021 {
Jamie Madille83d1a92013-10-24 17:49:33 -04001022 ensureRenderTarget();
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001023
Jamie Madill07bb8cf2013-10-24 17:49:44 -04001024 if (isValidLevel(level))
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001025 {
Jamie Madill169d1112013-10-24 17:49:37 -04001026 updateStorageLevel(level);
Jamie Madill07edd442013-07-19 16:36:58 -04001027
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001028 gl::Rectangle sourceRect;
1029 sourceRect.x = x;
1030 sourceRect.width = width;
1031 sourceRect.y = y;
1032 sourceRect.height = height;
1033
Geoff Lange4a492b2014-06-19 14:14:41 -04001034 mRenderer->copyImage(source, sourceRect, gl::GetFormat(getInternalFormat(0)),
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001035 xoffset, yoffset, zoffset, mTexStorage, level);
1036 }
1037 }
1038}
1039
Jamie Madillf8989902013-07-19 16:36:58 -04001040bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState) const
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001041{
Jamie Madilld3d2a342013-10-07 10:46:35 -04001042 GLsizei width = getBaseLevelWidth();
1043 GLsizei height = getBaseLevelHeight();
Jamie Madillb8f8b892014-01-07 10:12:50 -05001044 GLsizei depth = getLayers(0);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001045
1046 if (width <= 0 || height <= 0 || depth <= 0)
1047 {
1048 return false;
1049 }
1050
Geoff Langc0b9ef42014-07-02 10:02:37 -04001051 // TODO(geofflang): use context's texture caps
1052 if (!mRenderer->getRendererTextureCaps().get(getBaseLevelInternalFormat()).filtering)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001053 {
Jamie Madillf8989902013-07-19 16:36:58 -04001054 if (samplerState.magFilter != GL_NEAREST ||
1055 (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST))
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001056 {
1057 return false;
1058 }
1059 }
1060
Jamie Madillf8989902013-07-19 16:36:58 -04001061 if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001062 {
1063 return false;
1064 }
1065
1066 return true;
1067}
1068
1069bool Texture2DArray::isMipmapComplete() const
1070{
Geoff Lang98705b72014-03-31 16:00:03 -04001071 int levelCount = mipLevels();
Jamie Madill07edd442013-07-19 16:36:58 -04001072
Geoff Lang98705b72014-03-31 16:00:03 -04001073 for (int level = 1; level < levelCount; level++)
Jamie Madill07edd442013-07-19 16:36:58 -04001074 {
1075 if (!isLevelComplete(level))
1076 {
1077 return false;
1078 }
1079 }
1080
1081 return true;
1082}
1083
1084bool Texture2DArray::isLevelComplete(int level) const
1085{
Jamie Madillb8f8b892014-01-07 10:12:50 -05001086 ASSERT(level >= 0 && level < (int)ArraySize(mImageArray));
Jamie Madill07edd442013-07-19 16:36:58 -04001087
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001088 if (isImmutable())
1089 {
1090 return true;
1091 }
1092
Jamie Madilld3d2a342013-10-07 10:46:35 -04001093 GLsizei width = getBaseLevelWidth();
1094 GLsizei height = getBaseLevelHeight();
Jamie Madillb8f8b892014-01-07 10:12:50 -05001095 GLsizei layers = getLayers(0);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001096
Jamie Madillb8f8b892014-01-07 10:12:50 -05001097 if (width <= 0 || height <= 0 || layers <= 0)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001098 {
1099 return false;
1100 }
1101
Jamie Madill07edd442013-07-19 16:36:58 -04001102 if (level == 0)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001103 {
Jamie Madill07edd442013-07-19 16:36:58 -04001104 return true;
1105 }
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001106
Jamie Madill07edd442013-07-19 16:36:58 -04001107 if (getInternalFormat(level) != getInternalFormat(0))
1108 {
1109 return false;
1110 }
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001111
Jamie Madill07edd442013-07-19 16:36:58 -04001112 if (getWidth(level) != std::max(1, width >> level))
1113 {
1114 return false;
1115 }
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001116
Jamie Madill07edd442013-07-19 16:36:58 -04001117 if (getHeight(level) != std::max(1, height >> level))
1118 {
1119 return false;
1120 }
1121
Jamie Madillb8f8b892014-01-07 10:12:50 -05001122 if (getLayers(level) != layers)
Jamie Madill07edd442013-07-19 16:36:58 -04001123 {
1124 return false;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001125 }
1126
1127 return true;
1128}
1129
Jamie Madille83d1a92013-10-24 17:49:33 -04001130unsigned int Texture2DArray::getRenderTargetSerial(GLint level, GLint layer)
Geoff Lang8040f572013-07-25 16:49:54 -04001131{
Jamie Madille83d1a92013-10-24 17:49:33 -04001132 return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001133}
1134
Jamie Madill07bb8cf2013-10-24 17:49:44 -04001135bool Texture2DArray::isValidLevel(int level) const
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001136{
Nicolas Capensbf712d02014-03-31 14:23:35 -04001137 return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001138}
1139
Jamie Madill73b5d062013-10-24 17:49:38 -04001140void Texture2DArray::initializeStorage(bool renderTarget)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001141{
Jamie Madill884a4622013-10-24 17:49:41 -04001142 // Only initialize the first time this texture is used as a render target or shader resource
1143 if (mTexStorage)
1144 {
1145 return;
1146 }
1147
1148 // do not attempt to create storage for nonexistant data
1149 if (!isLevelComplete(0))
1150 {
1151 return;
1152 }
1153
1154 bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
1155
1156 setCompleteTexStorage(createCompleteStorage(createRenderTarget));
1157 ASSERT(mTexStorage);
1158
1159 // flush image data to the storage
1160 updateStorage();
1161}
1162
1163rx::TextureStorageInterface2DArray *Texture2DArray::createCompleteStorage(bool renderTarget) const
1164{
Jamie Madilld3d2a342013-10-07 10:46:35 -04001165 GLsizei width = getBaseLevelWidth();
1166 GLsizei height = getBaseLevelHeight();
Jamie Madillb8f8b892014-01-07 10:12:50 -05001167 GLsizei depth = getLayers(0);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001168
Jamie Madill884a4622013-10-24 17:49:41 -04001169 ASSERT(width > 0 && height > 0 && depth > 0);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001170
Jamie Madill884a4622013-10-24 17:49:41 -04001171 // use existing storage level count, when previously specified by TexStorage*D
Nicolas Capensbf712d02014-03-31 14:23:35 -04001172 GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001173
Nicolas Capensbf712d02014-03-31 14:23:35 -04001174 return new rx::TextureStorageInterface2DArray(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels);
Jamie Madill884a4622013-10-24 17:49:41 -04001175}
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001176
Jamie Madill884a4622013-10-24 17:49:41 -04001177void Texture2DArray::setCompleteTexStorage(rx::TextureStorageInterface2DArray *newCompleteTexStorage)
1178{
1179 SafeDelete(mTexStorage);
1180 mTexStorage = newCompleteTexStorage;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001181 mDirtyImages = true;
Jamie Madill884a4622013-10-24 17:49:41 -04001182
1183 // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only
1184 ASSERT(!mTexStorage->isManaged());
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001185}
1186
Jamie Madill169d1112013-10-24 17:49:37 -04001187void Texture2DArray::updateStorage()
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001188{
Geoff Lang946b9482014-05-12 16:37:25 -04001189 ASSERT(mTexStorage != NULL);
1190 GLint storageLevels = mTexStorage->getLevelCount();
1191 for (int level = 0; level < storageLevels; level++)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001192 {
Jamie Madilld9b9a502013-10-10 17:46:13 -04001193 if (isLevelComplete(level))
1194 {
Jamie Madill169d1112013-10-24 17:49:37 -04001195 updateStorageLevel(level);
Jamie Madilld9b9a502013-10-10 17:46:13 -04001196 }
Jamie Madill07edd442013-07-19 16:36:58 -04001197 }
1198}
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001199
Jamie Madill169d1112013-10-24 17:49:37 -04001200void Texture2DArray::updateStorageLevel(int level)
Jamie Madill07edd442013-07-19 16:36:58 -04001201{
Jamie Madillaee7ad82013-10-10 16:07:32 -04001202 ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts));
1203 ASSERT(isLevelComplete(level));
1204
Jamie Madill07edd442013-07-19 16:36:58 -04001205 for (int layer = 0; layer < mLayerCounts[level]; layer++)
1206 {
Jamie Madillaee7ad82013-10-10 16:07:32 -04001207 ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL);
1208 if (mImageArray[level][layer]->isDirty())
Jamie Madill07edd442013-07-19 16:36:58 -04001209 {
Jamie Madillaee7ad82013-10-10 16:07:32 -04001210 commitRect(level, 0, 0, layer, getWidth(level), getHeight(level));
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001211 }
1212 }
1213}
1214
Jamie Madille83d1a92013-10-24 17:49:33 -04001215bool Texture2DArray::ensureRenderTarget()
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001216{
Jamie Madill884a4622013-10-24 17:49:41 -04001217 initializeStorage(true);
1218
Jamie Madillb8f8b892014-01-07 10:12:50 -05001219 if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getLayers(0) > 0)
Jamie Madille83d1a92013-10-24 17:49:33 -04001220 {
Jamie Madill884a4622013-10-24 17:49:41 -04001221 ASSERT(mTexStorage);
1222 if (!mTexStorage->isRenderTarget())
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001223 {
Jamie Madill884a4622013-10-24 17:49:41 -04001224 rx::TextureStorageInterface2DArray *newRenderTargetStorage = createCompleteStorage(true);
1225
1226 if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage))
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001227 {
Jamie Madill884a4622013-10-24 17:49:41 -04001228 delete newRenderTargetStorage;
Jamie Madille83d1a92013-10-24 17:49:33 -04001229 return gl::error(GL_OUT_OF_MEMORY, false);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001230 }
Jamie Madill884a4622013-10-24 17:49:41 -04001231
1232 setCompleteTexStorage(newRenderTargetStorage);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001233 }
1234 }
1235
Jamie Madille83d1a92013-10-24 17:49:33 -04001236 return (mTexStorage && mTexStorage->isRenderTarget());
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001237}
1238
Geoff Lang8040f572013-07-25 16:49:54 -04001239rx::RenderTarget *Texture2DArray::getRenderTarget(GLint level, GLint layer)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001240{
Geoff Lang8040f572013-07-25 16:49:54 -04001241 // ensure the underlying texture is created
Jamie Madill2ebab852013-10-24 17:49:42 -04001242 if (!ensureRenderTarget())
Geoff Lang8040f572013-07-25 16:49:54 -04001243 {
1244 return NULL;
1245 }
1246
Jamie Madill169d1112013-10-24 17:49:37 -04001247 updateStorageLevel(level);
Geoff Lang8040f572013-07-25 16:49:54 -04001248
1249 // ensure this is NOT a depth texture
1250 if (isDepth(level))
1251 {
1252 return NULL;
1253 }
1254
1255 return mTexStorage->getRenderTarget(level, layer);
1256}
1257
1258rx::RenderTarget *Texture2DArray::getDepthStencil(GLint level, GLint layer)
1259{
1260 // ensure the underlying texture is created
Jamie Madill2ebab852013-10-24 17:49:42 -04001261 if (!ensureRenderTarget())
Geoff Lang8040f572013-07-25 16:49:54 -04001262 {
1263 return NULL;
1264 }
1265
Jamie Madill169d1112013-10-24 17:49:37 -04001266 updateStorageLevel(level);
Geoff Lang8040f572013-07-25 16:49:54 -04001267
1268 // ensure this is a depth texture
1269 if (!isDepth(level))
1270 {
1271 return NULL;
1272 }
1273
1274 return mTexStorage->getRenderTarget(level, layer);
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001275}
1276
Geoff Lang005df412013-10-16 14:12:50 -04001277void Texture2DArray::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001278{
1279 // If there currently is a corresponding storage texture image, it has these parameters
Jamie Madilld3d2a342013-10-07 10:46:35 -04001280 const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
1281 const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
Jamie Madillb8f8b892014-01-07 10:12:50 -05001282 const int storageDepth = getLayers(0);
Geoff Lang005df412013-10-16 14:12:50 -04001283 const GLenum storageFormat = getBaseLevelInternalFormat();
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001284
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +00001285 for (int layer = 0; layer < mLayerCounts[level]; layer++)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001286 {
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +00001287 delete mImageArray[level][layer];
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001288 }
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +00001289 delete[] mImageArray[level];
Jamie Madill152ed092013-10-09 17:01:15 -04001290 mImageArray[level] = NULL;
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001291 mLayerCounts[level] = depth;
1292
Jamie Madill152ed092013-10-09 17:01:15 -04001293 if (depth > 0)
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +00001294 {
Jamie Madill152ed092013-10-09 17:01:15 -04001295 mImageArray[level] = new rx::Image*[depth]();
1296
1297 for (int layer = 0; layer < mLayerCounts[level]; layer++)
1298 {
1299 mImageArray[level][layer] = mRenderer->createImage();
1300 mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, width, height, 1, false);
1301 }
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +00001302 }
1303
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001304 if (mTexStorage)
1305 {
Nicolas Capensbf712d02014-03-31 14:23:35 -04001306 const int storageLevels = mTexStorage->getLevelCount();
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001307
1308 if ((level >= storageLevels && storageLevels != 0) ||
1309 width != storageWidth ||
1310 height != storageHeight ||
1311 depth != storageDepth ||
1312 internalformat != storageFormat) // Discard mismatched storage
1313 {
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +00001314 for (int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001315 {
shannonwoods@chromium.org644f7662013-05-30 00:02:07 +00001316 for (int layer = 0; layer < mLayerCounts[level]; layer++)
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001317 {
1318 mImageArray[level][layer]->markDirty();
1319 }
1320 }
1321
1322 delete mTexStorage;
1323 mTexStorage = NULL;
1324 mDirtyImages = true;
1325 }
1326 }
1327}
1328
1329void Texture2DArray::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height)
1330{
Jamie Madillb8f8b892014-01-07 10:12:50 -05001331 if (isValidLevel(level) && layerTarget < getLayers(level))
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001332 {
Brandon Jones6518fe22014-07-08 15:16:52 -07001333 rx::ImageD3D *image = rx::ImageD3D::makeImageD3D(mImageArray[level][layerTarget]);
Jamie Madill169d1112013-10-24 17:49:37 -04001334 if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, layerTarget, width, height))
shannon.woods%transgaming.com@gtempaccount.com7625f792013-04-13 03:46:07 +00001335 {
1336 image->markClean();
1337 }
1338 }
1339}
1340
daniel@transgaming.com95a758f2012-07-12 15:17:06 +00001341}