blob: f209d5cbd87374aa5dfca80dacbf68c118223a56 [file] [log] [blame]
Geoff Langf9a6f082015-01-22 13:32:49 -05001//
2// Copyright 2015 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// TextureGL.cpp: Implements the class methods for TextureGL.
8
9#include "libANGLE/renderer/gl/TextureGL.h"
10
11#include "common/debug.h"
Geoff Langc05f7062015-03-10 09:50:57 -070012#include "common/utilities.h"
Jamie Madill67102f02015-03-16 10:41:42 -040013#include "libANGLE/State.h"
Geoff Langc05f7062015-03-10 09:50:57 -070014#include "libANGLE/angletypes.h"
15#include "libANGLE/formatutils.h"
16#include "libANGLE/renderer/gl/BufferGL.h"
17#include "libANGLE/renderer/gl/FunctionsGL.h"
18#include "libANGLE/renderer/gl/StateManagerGL.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050019
20namespace rx
21{
22
Geoff Langc05f7062015-03-10 09:50:57 -070023static void SetUnpackStateForTexImage(StateManagerGL *stateManager, const gl::PixelUnpackState &unpack)
24{
25 const gl::Buffer *unpackBuffer = unpack.pixelBuffer.get();
26 if (unpackBuffer != nullptr)
27 {
28 UNIMPLEMENTED();
29 }
30 if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
31 {
32 UNIMPLEMENTED();
33 }
34 stateManager->setPixelUnpackState(unpack.alignment, unpack.rowLength);
35}
36
37static bool UseTexImage2D(GLenum textureType)
38{
39 return textureType == GL_TEXTURE_2D || textureType == GL_TEXTURE_CUBE_MAP;
40}
41
42static bool UseTexImage3D(GLenum textureType)
43{
44 return textureType == GL_TEXTURE_2D_ARRAY || textureType == GL_TEXTURE_3D;
45}
46
Geoff Lang968992e2015-03-17 18:01:49 -040047static bool CompatibleTextureTarget(GLenum textureType, GLenum textureTarget)
Geoff Langc05f7062015-03-10 09:50:57 -070048{
49 if (textureType != GL_TEXTURE_CUBE_MAP)
50 {
51 return textureType == textureTarget;
52 }
53 else
54 {
55 return gl::IsCubeMapTextureTarget(textureType);
56 }
57}
58
59TextureGL::TextureGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
60 : TextureImpl(),
61 mTextureType(type),
62 mFunctions(functions),
63 mStateManager(stateManager),
64 mAppliedSamplerState(),
65 mTextureID(0)
66{
67 ASSERT(mFunctions);
68 ASSERT(mStateManager);
69
70 mFunctions->genTextures(1, &mTextureID);
71}
Geoff Langf9a6f082015-01-22 13:32:49 -050072
73TextureGL::~TextureGL()
Geoff Langc05f7062015-03-10 09:50:57 -070074{
75 if (mTextureID)
76 {
77 mFunctions->deleteTextures(1, &mTextureID);
78 mTextureID = 0;
79 }
80}
Geoff Langf9a6f082015-01-22 13:32:49 -050081
82void TextureGL::setUsage(GLenum usage)
83{
Geoff Langc05f7062015-03-10 09:50:57 -070084 // GL_ANGLE_texture_usage not implemented for desktop GL
85 UNREACHABLE();
Geoff Langf9a6f082015-01-22 13:32:49 -050086}
87
88gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
89 const gl::PixelUnpackState &unpack, const uint8_t *pixels)
90{
Geoff Lang968992e2015-03-17 18:01:49 -040091 (void)&CompatibleTextureTarget; // Reference this function to avoid warnings.
92 ASSERT(CompatibleTextureTarget(mTextureType, target));
Geoff Langc05f7062015-03-10 09:50:57 -070093
94 SetUnpackStateForTexImage(mStateManager, unpack);
95
96 mStateManager->bindTexture(mTextureType, mTextureID);
97 if (UseTexImage2D(mTextureType))
Jamie Madill67102f02015-03-16 10:41:42 -040098 {
Geoff Langc05f7062015-03-10 09:50:57 -070099 ASSERT(size.depth == 1);
100 mFunctions->texImage2D(target, level, internalFormat, size.width, size.height, 0, format, type, pixels);
101 }
102 else if (UseTexImage3D(mTextureType))
103 {
104 mFunctions->texImage3D(target, level, internalFormat, size.width, size.height, size.depth, 0, format, type, pixels);
105 }
106 else
107 {
108 UNREACHABLE();
Jamie Madill67102f02015-03-16 10:41:42 -0400109 }
110
Geoff Langc05f7062015-03-10 09:50:57 -0700111 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500112}
113
114gl::Error TextureGL::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
115 const gl::PixelUnpackState &unpack, const uint8_t *pixels)
116{
Geoff Lang968992e2015-03-17 18:01:49 -0400117 ASSERT(CompatibleTextureTarget(mTextureType, target));
Geoff Langc05f7062015-03-10 09:50:57 -0700118
119 SetUnpackStateForTexImage(mStateManager, unpack);
120
121 mStateManager->bindTexture(mTextureType, mTextureID);
122 if (UseTexImage2D(mTextureType))
Jamie Madill67102f02015-03-16 10:41:42 -0400123 {
Geoff Langc05f7062015-03-10 09:50:57 -0700124 ASSERT(area.z == 0 && area.depth == 1);
125 mFunctions->texSubImage2D(target, level, area.x, area.y, area.width, area.height, format, type, pixels);
126 }
127 else if (UseTexImage3D(mTextureType))
128 {
129 mFunctions->texSubImage3D(target, level, area.x, area.y, area.z, area.width, area.height, area.depth,
130 format, type, pixels);
131 }
132 else
133 {
134 UNREACHABLE();
Jamie Madill67102f02015-03-16 10:41:42 -0400135 }
136
Geoff Langc05f7062015-03-10 09:50:57 -0700137 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500138}
139
140gl::Error TextureGL::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
141 const gl::PixelUnpackState &unpack, const uint8_t *pixels)
142{
Geoff Lang968992e2015-03-17 18:01:49 -0400143 ASSERT(CompatibleTextureTarget(mTextureType, target));
Geoff Langc05f7062015-03-10 09:50:57 -0700144
145 SetUnpackStateForTexImage(mStateManager, unpack);
146
147 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
148 size_t depthPitch = internalFormatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height,
149 unpack.alignment, unpack.rowLength);
150 size_t dataSize = internalFormatInfo.computeBlockSize(GL_UNSIGNED_BYTE, size.width, size.height) * depthPitch;
151
152 mStateManager->bindTexture(mTextureType, mTextureID);
153 if (UseTexImage2D(mTextureType))
Jamie Madill67102f02015-03-16 10:41:42 -0400154 {
Geoff Langc05f7062015-03-10 09:50:57 -0700155 ASSERT(size.depth == 1);
156 mFunctions->compressedTexImage2D(target, level, internalFormat, size.width, size.height, 0, dataSize, pixels);
157 }
158 else if (UseTexImage3D(mTextureType))
159 {
160 mFunctions->compressedTexImage3D(target, level, internalFormat, size.width, size.height, size.depth, 0,
161 dataSize, pixels);
162 }
163 else
164 {
165 UNREACHABLE();
Jamie Madill67102f02015-03-16 10:41:42 -0400166 }
167
Geoff Langc05f7062015-03-10 09:50:57 -0700168 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500169}
170
171gl::Error TextureGL::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
172 const gl::PixelUnpackState &unpack, const uint8_t *pixels)
173{
Geoff Lang968992e2015-03-17 18:01:49 -0400174 ASSERT(CompatibleTextureTarget(mTextureType, target));
Geoff Langc05f7062015-03-10 09:50:57 -0700175
176 SetUnpackStateForTexImage(mStateManager, unpack);
177
178 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(format);
179 size_t depthPitch = internalFormatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height,
180 unpack.alignment, unpack.rowLength);
181 size_t dataSize = internalFormatInfo.computeBlockSize(GL_UNSIGNED_BYTE, area.width, area.height) * depthPitch;
182
183 mStateManager->bindTexture(mTextureType, mTextureID);
184 if (UseTexImage2D(mTextureType))
Jamie Madill67102f02015-03-16 10:41:42 -0400185 {
Geoff Langc05f7062015-03-10 09:50:57 -0700186 ASSERT(area.z == 0 && area.depth == 1);
187 mFunctions->compressedTexSubImage2D(target, level, area.x, area.y, area.width, area.height, format, dataSize,
188 pixels);
189 }
190 else if (UseTexImage3D(mTextureType))
191 {
192 mFunctions->compressedTexSubImage3D(target, level, area.x, area.y, area.z, area.width, area.height, area.depth,
193 format, dataSize, pixels);
194 }
195 else
196 {
197 UNREACHABLE();
Jamie Madill67102f02015-03-16 10:41:42 -0400198 }
199
Geoff Langc05f7062015-03-10 09:50:57 -0700200 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500201}
202
203gl::Error TextureGL::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
204 const gl::Framebuffer *source)
205{
206 UNIMPLEMENTED();
207 return gl::Error(GL_INVALID_OPERATION);
208}
209
210gl::Error TextureGL::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
211 const gl::Framebuffer *source)
212{
213 UNIMPLEMENTED();
214 return gl::Error(GL_INVALID_OPERATION);
215}
216
217gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
218{
Geoff Langc05f7062015-03-10 09:50:57 -0700219 // TODO: emulate texture storage with TexImage calls if on GL version <4.2 or the
220 // ARB_texture_storage extension is not available.
221
222 mStateManager->bindTexture(mTextureType, mTextureID);
223 if (UseTexImage2D(mTextureType))
224 {
225 ASSERT(size.depth == 1);
226 mFunctions->texStorage2D(target, levels, internalFormat, size.width, size.height);
227 }
228 else if (UseTexImage3D(mTextureType))
229 {
230 mFunctions->texStorage3D(target, levels, internalFormat, size.width, size.height, size.depth);
231 }
232 else
233 {
234 UNREACHABLE();
235 }
236
237 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500238}
239
240gl::Error TextureGL::generateMipmaps()
241{
Geoff Langc05f7062015-03-10 09:50:57 -0700242 mStateManager->bindTexture(mTextureType, mTextureID);
243 mFunctions->generateMipmap(mTextureType);
244 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500245}
246
247void TextureGL::bindTexImage(egl::Surface *surface)
248{
249 UNIMPLEMENTED();
250}
251
252void TextureGL::releaseTexImage()
253{
254 UNIMPLEMENTED();
255}
256
Geoff Langc05f7062015-03-10 09:50:57 -0700257template <typename T>
258static inline void SyncSamplerStateMember(const FunctionsGL *functions, const gl::SamplerState &newState,
259 gl::SamplerState &curState, GLenum textureType, GLenum name,
260 T(gl::SamplerState::*samplerMember))
261{
262 if (curState.*samplerMember != newState.*samplerMember)
263 {
264 curState.*samplerMember = newState.*samplerMember;
265 functions->texParameterf(textureType, name, curState.*samplerMember);
266 }
267}
268
269void TextureGL::syncSamplerState(const gl::SamplerState &samplerState) const
270{
271 if (mAppliedSamplerState != samplerState)
272 {
273 mStateManager->bindTexture(mTextureType, mTextureID);
274 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MIN_FILTER, &gl::SamplerState::minFilter);
275 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAG_FILTER, &gl::SamplerState::magFilter);
276 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_S, &gl::SamplerState::wrapS);
277 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_T, &gl::SamplerState::wrapT);
278 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_R, &gl::SamplerState::wrapR);
279 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_ANISOTROPY_EXT, &gl::SamplerState::maxAnisotropy);
280 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_BASE_LEVEL, &gl::SamplerState::baseLevel);
281 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_LEVEL, &gl::SamplerState::maxLevel);
282 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MIN_LOD, &gl::SamplerState::minLod);
283 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod);
284 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode);
285 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc);
286 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_R, &gl::SamplerState::swizzleRed);
287 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_G, &gl::SamplerState::swizzleGreen);
288 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_B, &gl::SamplerState::swizzleBlue);
289 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_A, &gl::SamplerState::swizzleAlpha);
290 }
291}
292
293GLuint TextureGL::getTextureID() const
294{
295 return mTextureID;
296}
297
Geoff Langf9a6f082015-01-22 13:32:49 -0500298}