blob: d3a8c9c10994e9addaaa462cca7d1dd1dd6463ad [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 {
Geoff Langfb2a5592015-03-20 11:25:37 -040055 return gl::IsCubeMapTextureTarget(textureTarget);
Geoff Langc05f7062015-03-10 09:50:57 -070056 }
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 Langfb2a5592015-03-20 11:25:37 -040091 UNUSED_ASSERTION_VARIABLE(&CompatibleTextureTarget); // Reference this function to avoid warnings.
Geoff Lang968992e2015-03-17 18:01:49 -040092 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);
Geoff Lang1c0ad622015-03-24 10:27:45 -0400226 if (mFunctions->texStorage2D)
227 {
228 mFunctions->texStorage2D(target, levels, internalFormat, size.width, size.height);
229 }
230 else
231 {
232 // Make sure no pixel unpack buffer is bound
233 mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
234
235 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
236
237 // Internal format must be sized
238 ASSERT(internalFormatInfo.pixelBytes != 0);
239
240 for (size_t level = 0; level < levels; level++)
241 {
242 gl::Extents levelSize(std::max(size.width >> level, 1),
243 std::max(size.height >> level, 1),
244 1);
245
246 if (mTextureType == GL_TEXTURE_2D)
247 {
248 mFunctions->texImage2D(target, level, internalFormat, levelSize.width, levelSize.height,
249 0, internalFormatInfo.format, internalFormatInfo.type, nullptr);
250 }
251 else if (mTextureType == GL_TEXTURE_CUBE_MAP)
252 {
253 for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget; face++)
254 {
255 mFunctions->texImage2D(face, level, internalFormat, levelSize.width, levelSize.height,
256 0, internalFormatInfo.format, internalFormatInfo.type, nullptr);
257 }
258 }
259 else
260 {
261 UNREACHABLE();
262 }
263 }
264 }
Geoff Langc05f7062015-03-10 09:50:57 -0700265 }
266 else if (UseTexImage3D(mTextureType))
267 {
Geoff Lang1c0ad622015-03-24 10:27:45 -0400268 if (mFunctions->texStorage3D)
269 {
270 mFunctions->texStorage3D(target, levels, internalFormat, size.width, size.height, size.depth);
271 }
272 else
273 {
274 // Make sure no pixel unpack buffer is bound
275 mStateManager->bindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
276
277 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
278
279 // Internal format must be sized
280 ASSERT(internalFormatInfo.pixelBytes != 0);
281
282 for (size_t i = 0; i < levels; i++)
283 {
284 gl::Extents levelSize(std::max(size.width >> i, 1),
285 std::max(size.height >> i, 1),
286 mTextureType == GL_TEXTURE_3D ? std::max(size.depth >> i, 1) : size.depth);
287
288 mFunctions->texImage3D(target, i, internalFormat, levelSize.width, levelSize.height, levelSize.depth,
289 0, internalFormatInfo.format, internalFormatInfo.type, nullptr);
290 }
291 }
Geoff Langc05f7062015-03-10 09:50:57 -0700292 }
293 else
294 {
295 UNREACHABLE();
296 }
297
298 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500299}
300
301gl::Error TextureGL::generateMipmaps()
302{
Geoff Langc05f7062015-03-10 09:50:57 -0700303 mStateManager->bindTexture(mTextureType, mTextureID);
304 mFunctions->generateMipmap(mTextureType);
305 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500306}
307
308void TextureGL::bindTexImage(egl::Surface *surface)
309{
310 UNIMPLEMENTED();
311}
312
313void TextureGL::releaseTexImage()
314{
315 UNIMPLEMENTED();
316}
317
Geoff Langc05f7062015-03-10 09:50:57 -0700318template <typename T>
319static inline void SyncSamplerStateMember(const FunctionsGL *functions, const gl::SamplerState &newState,
320 gl::SamplerState &curState, GLenum textureType, GLenum name,
321 T(gl::SamplerState::*samplerMember))
322{
323 if (curState.*samplerMember != newState.*samplerMember)
324 {
325 curState.*samplerMember = newState.*samplerMember;
326 functions->texParameterf(textureType, name, curState.*samplerMember);
327 }
328}
329
330void TextureGL::syncSamplerState(const gl::SamplerState &samplerState) const
331{
332 if (mAppliedSamplerState != samplerState)
333 {
334 mStateManager->bindTexture(mTextureType, mTextureID);
335 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MIN_FILTER, &gl::SamplerState::minFilter);
336 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAG_FILTER, &gl::SamplerState::magFilter);
337 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_S, &gl::SamplerState::wrapS);
338 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_T, &gl::SamplerState::wrapT);
339 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_R, &gl::SamplerState::wrapR);
340 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_ANISOTROPY_EXT, &gl::SamplerState::maxAnisotropy);
341 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_BASE_LEVEL, &gl::SamplerState::baseLevel);
342 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_LEVEL, &gl::SamplerState::maxLevel);
343 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MIN_LOD, &gl::SamplerState::minLod);
344 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod);
345 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode);
346 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc);
347 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_R, &gl::SamplerState::swizzleRed);
348 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_G, &gl::SamplerState::swizzleGreen);
349 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_B, &gl::SamplerState::swizzleBlue);
350 SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_A, &gl::SamplerState::swizzleAlpha);
351 }
352}
353
354GLuint TextureGL::getTextureID() const
355{
356 return mTextureID;
357}
358
Geoff Langf9a6f082015-01-22 13:32:49 -0500359}