Cogs.Core
TexturesGLES30.cpp
1#include "TexturesGLES30.h"
2
3#include <algorithm>
4
5#include "FormatsGLES30.h"
6#include "CapabilitiesGLES30.h"
7#include "ContextGLES30.h"
8
9#include "Foundation/Logging/Logger.h"
10
11using namespace Cogs;
12
13namespace
14{
15 Cogs::Logging::Log logger = Cogs::Logging::getLogger("TexturesGLES30");
16
17
18 Cogs::TextureHandle logAndReturnInvalidHandle(const Cogs::TextureDescription& desc)
19 {
20 LOG_ERROR(logger, "Illegal %s description (width=%u, height=%u, depth=%u, layers=%u, faces=%u, levels=%u, samples=%u)",
21 getResourceDimensionsName(desc.target), desc.width, desc.height, desc.depth, desc.layers, desc.faces, desc.levels, desc.samples);
23 }
24
25 // Clamp the sample count to max supported for a particular format
26 uint32_t clampFormatSampleCount(CapabilitiesGLES30* caps, Cogs::TextureFormat format, uint8_t numSamples)
27 {
28 const OpenGLES30::DataFormatInfo& fmt = OpenGLES30::DataFormats[size_t(format)];
29
30 // Clamp sample count
31 GLint maxSampleCount = 0;
32 glGetInternalformativ(GL_RENDERBUFFER, fmt.internalFormat, GL_SAMPLES, 1, &maxSampleCount);
33 assert(0 <= maxSampleCount);
34
35 if (caps->getDeviceCapabilities().MaxSamples < static_cast<unsigned>(maxSampleCount)) {
36 LOG_WARNING_ONCE(logger, "getInternalFormat(fmt=0x%04x) returned maxSampleCount=%d, but glGetIntegerv(GL_MAX_SAMPLES) returned %u, clamping.",
37 fmt.internalFormat, maxSampleCount, caps->getDeviceCapabilities().MaxSamples);
38 maxSampleCount = caps->getDeviceCapabilities().MaxSamples;
39 }
40 if (uint32_t(maxSampleCount) < numSamples) {
41 LOG_DEBUG_ONCE(logger, "Requested sample count %u greater than maximum %d for format %s, clamping.",
42 numSamples, maxSampleCount, getFormatInfo(format)->name);
43 return maxSampleCount;
44 }
45 return numSamples;
46 }
47
48}
49
51{
52 const bool generateMips = (desc.flags & TextureFlags::GenerateMipMaps) != 0;
53
54 TextureGLES30 texture{ };
55 texture.width = desc.width;
56 texture.height = desc.height;
57 texture.depth = 1;
58 texture.estimatedByteSize = uint32_t(desc.estimateMemorySize());
59 texture.flags = desc.flags;
60 texture.numSamples = uint8_t(desc.samples);
61 texture.textureId = 0;
62 texture.renderBuffer = 0;
63 texture.fbo = 0;
64 texture.format = desc.format;
65 texture.cubeMap = false;
66 texture.hasMipmaps = generateMips || desc.levels > 1;
67
68 // Sanity checks
69 const OpenGLES30::DataFormatInfo& fmt = OpenGLES30::DataFormats[size_t(texture.format)];
70 if (fmt.isTextureFormat == 0) {
72 }
73 if (data && fmt.isCompressed) {
74 texture.estimatedByteSize = uint32_t(data->getSize());
75 }
76
77 switch (desc.target) {
78 case ResourceDimensions::Unknown:
79 case ResourceDimensions::Buffer:
80 case ResourceDimensions::Texture1D:
81 case ResourceDimensions::Texture1DArray:
82 case ResourceDimensions::Texture3DArray:
83 case ResourceDimensions::TextureCubeArray:
84 case ResourceDimensions::Texture2DMSArray:
85 LOG_ERROR(logger, "Unsupported texture resource dimension %s", getResourceDimensionsName(desc.target));
87
88 case ResourceDimensions::Texture2DMS:
89 if (desc.width == 0 || desc.height == 0 || desc.depth != 1 || desc.layers != 1 || desc.faces != 1 || desc.samples == 0) {
90 return logAndReturnInvalidHandle(desc);
91 }
92 else {
93 texture.target = GL_TEXTURE_2D_MULTISAMPLE; // Not directly supported, used to specify that data is in a renderbuffer
94
95 texture.numSamples = static_cast<uint8_t>(clampFormatSampleCount(caps, texture.format, texture.numSamples));
96
97 // Set up renderbuffer
98 glGenRenderbuffers(1, &texture.renderBuffer);
99 glBindRenderbuffer(GL_RENDERBUFFER, texture.renderBuffer);
100 glRenderbufferStorageMultisample(GL_RENDERBUFFER, texture.numSamples, fmt.internalFormat, texture.width, texture.height);
101 glBindRenderbuffer(GL_RENDERBUFFER, 0);
102
103 // Set up framebuffer
104 GLenum framebufferAttachment = (texture.flags & Cogs::TextureFlags::DepthBuffer) ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0;
105 glGenFramebuffers(1, &texture.fbo);
106 glBindFramebuffer(GL_READ_FRAMEBUFFER, texture.fbo);
107 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, framebufferAttachment, GL_RENDERBUFFER, texture.renderBuffer);
108 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
109
110 GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
111 if (status != GL_FRAMEBUFFER_COMPLETE) {
112 LOG_ERROR(logger, "Failed to create multisample texture rendertarget: %s", OpenGLES30::framebuffersStatusString(status));
113 glDeleteFramebuffers(1, &texture.fbo);
114 glDeleteRenderbuffers(1, &texture.renderBuffer);
116 }
117
118 return textures.addResource(texture);
119 }
120 break;
121
122 case ResourceDimensions::Texture2D:
123 if (desc.width == 0 || desc.height == 0 || desc.depth != 1 || desc.layers != 1 || desc.faces != 1 || desc.samples != 1) {
124 return logAndReturnInvalidHandle(desc);
125 }
126 texture.target = GL_TEXTURE_2D;
127 break;
128 case ResourceDimensions::Texture2DArray:
129 if (desc.width == 0 || desc.height == 0 || desc.depth != 1 || desc.layers == 0 || desc.faces != 1 || desc.samples != 1) {
130 return logAndReturnInvalidHandle(desc);
131 }
132 texture.target = GL_TEXTURE_2D_ARRAY;
133 texture.depth = desc.layers;
134 break;
135 case ResourceDimensions::Texture3D:
136 if (desc.width == 0 || desc.height == 0 || desc.depth == 0 || desc.layers != 1 || desc.faces != 1 || desc.samples != 1) {
137 return logAndReturnInvalidHandle(desc);
138 }
139 texture.target = GL_TEXTURE_3D;
140 texture.depth = desc.depth;
141 break;
142 case ResourceDimensions::TextureCube:
143 if (desc.width == 0 || desc.height == 0 || desc.depth != 1 || desc.layers != 1 || desc.faces != 6 || desc.samples != 1) {
144 return logAndReturnInvalidHandle(desc);
145 }
146 texture.target = GL_TEXTURE_CUBE_MAP;
147 texture.depth = desc.depth;
148 texture.cubeMap = true;
149 break;
150
151 case ResourceDimensions::RenderBuffer:
152 if (desc.width == 0 || desc.height == 0 || desc.depth != 1 || desc.layers != 1 || desc.faces != 1 || desc.levels != 1) {
153 return logAndReturnInvalidHandle(desc);
154 }
155 if (generateMips) {
156 LOG_ERROR(logger, "RenderBuffers do not support mipmaps");
158 }
159 texture.target = GL_RENDERBUFFER;
160 texture.numSamples = static_cast<uint8_t>(clampFormatSampleCount(caps, texture.format, texture.numSamples));
161 break;
162 default:
163 assert(false && "Invalid enum");
164 break;
165 }
166
167 GLuint textureLevels;
168 if (generateMips) {
169 textureLevels = 1 + static_cast<GLuint>(std::floor(std::log((double)std::max(desc.width, desc.height)) / std::log(2.0)));
170 }
171 else {
172 textureLevels = static_cast<GLuint>(desc.levels);
173 }
174
175
177
178 // If texture is a render buffer
179 if (texture.target == GL_RENDERBUFFER) {
180
181 texture.textureId = 0;
182 if (texture.flags & TextureFlags::ExternalTexture) {
183 assert(data != nullptr);
184 texture.renderBuffer = static_cast<GLuint>(data->externalHandle);
185 }
186 else {
187 glGenRenderbuffers(1, &texture.renderBuffer);
188 glBindRenderbuffer(GL_RENDERBUFFER, texture.renderBuffer);
189 glRenderbufferStorageMultisample(GL_RENDERBUFFER, texture.numSamples, fmt.internalFormat, texture.width, texture.height);
190 glBindRenderbuffer(GL_RENDERBUFFER, 0);
191 }
192 textureHandle = textures.addResource(texture);
193 }
194
195 // If texture is an actual texture
196 else {
197 if (desc.flags & TextureFlags::ExternalTexture) {
198 assert(data != nullptr);
199 texture.textureId = static_cast<GLuint>(data->externalHandle);
200 textureHandle = textures.addResource(texture);
201
202 if (generateMips) {
203 if (TextureGLES30* tex = context->bindTexture(textureHandle); tex) {
204 glGenerateMipmap(tex->target);
205 }
206 }
207 }
208 else {
209 glGenTextures(1, &texture.textureId);
210 textureHandle = textures.addResource(texture);
211
212 if (TextureGLES30* tex = context->bindTexture(textureHandle); tex) {
213 defineTextureData(tex, textureLevels);
214 if (data) {
215 uploadTextureData(*tex, *data, 0, 0, 0);
216 }
217 else if (generateMips) {
218 glGenerateMipmap(tex->target);
219 }
220 }
221 }
222 }
223
224 textureMemoryConsumption += texture.estimatedByteSize;
225 return textureHandle;
226}
227
228void Cogs::TexturesGLES30::uploadTextureData(TextureGLES30& tex,
229 const TextureData& data,
230 uint32_t layer_offset,
231 uint32_t face_offset,
232 uint32_t level_offset)
233{
234 assert(face_offset == 0 && "face_offset not handled");
235 assert(level_offset == 0 && "level_offset not handled");
236
237 const OpenGLES30::DataFormatInfo& fmt = OpenGLES30::DataFormats[size_t(tex.format)];
238 const bool isCompressed = fmt.isCompressed;
239 const GLenum target = tex.target;
240 const GLenum textureFormat = fmt.internalFormat;
241 const GLenum pixelType = fmt.type;
242 const GLenum pixelFormat = fmt.format;
243
244 if(context->uploadStatisticsEnabled) context->uploadStatisticsTextureUpload(data.getSize());
245
246 if (isCompressed) {
247 switch (target) {
248 case GL_TEXTURE_2D:
249 for (size_t j = 0; j < data.levels; ++j) {
250 TextureExtent ext = data.getExtent(j);
251 glCompressedTexSubImage2D(target, static_cast<GLint>(j), 0, 0, ext.width, ext.height, textureFormat, static_cast<GLsizei>(data.getLevelSize(j)), data.getData(0, 0, j));
252 }
253 break;
254 case GL_TEXTURE_CUBE_MAP:
255 for (size_t j = 0; j < data.levels; ++j) {
256 for (GLint c = 0; c < 6; ++c) {
257 TextureExtent ext = data.getExtent(j);
258 glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + c, static_cast<GLint>(j), 0, 0, ext.width, ext.height, textureFormat, GLsizei(data.getLevelSize(j)), data.getData(0, c, j));
259 }
260 }
261 break;
262 case GL_TEXTURE_2D_ARRAY:
263 for (size_t j = 0; j < data.levels; ++j) {
264 for (size_t l = 0; l < data.layers; ++l) {
265 TextureExtent ext = data.getExtent(j);
266 glCompressedTexSubImage3D(target, static_cast<GLint>(j), 0, 0, static_cast<GLint>(l), ext.width, ext.height, 1, textureFormat, GLsizei(data.getLevelSize(j)), data.getData(l, 0, j));
267 }
268 }
269 break;
270 case GL_TEXTURE_2D_MULTISAMPLE: [[fallthrough]];
271 case GL_TEXTURE_3D: [[fallthrough]];
272 case GL_INVALID_ENUM:
273 LOG_ERROR(logger, "Texture target #%04x cannot use compressed formats", target);
274 break;
275 }
276 }
277 else {
278 switch (target) {
279 case GL_TEXTURE_2D:
280 for (size_t j = 0; j < data.levels; ++j) {
281 TextureExtent ext = data.getExtent(j);
282 glTexSubImage2D(target, static_cast<GLint>(j), 0, 0, ext.width, ext.height, pixelFormat, pixelType, data.getData(0, 0, j));
283 }
284 break;
285 case GL_TEXTURE_2D_ARRAY:
286 for (size_t i = 0; i < data.layers; ++i) {
287 for (size_t j = 0; j < data.levels; ++j) {
288 TextureExtent ext = data.getExtent(j);
289 glTexSubImage3D(target, static_cast<GLint>(j),
290 0, 0, static_cast<GLint>(layer_offset + i), ext.width, ext.height, 1,
291 pixelFormat, pixelType, data.getData(i, 0, j));
292 }
293 }
294 break;
295 case GL_TEXTURE_3D:
296 for (size_t j = 0; j < data.levels; ++j) {
297 TextureExtent ext = data.getExtent(j);
298 glTexSubImage3D(target, static_cast<GLint>(j),
299 0, 0, 0, ext.width, ext.height, ext.depth,
300 pixelFormat, pixelType, data.getData(0, 0, j));
301 }
302 break;
303 case GL_TEXTURE_CUBE_MAP:
304 for (size_t j = 0; j < data.levels; ++j) {
305 for (GLint c = 0; c < 6; ++c) {
306 TextureExtent ext = data.getExtent(j);
307 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + c, (GLint)j,
308 0, 0, ext.width, ext.height,
309 pixelFormat, pixelType, data.getData(0, c, j));
310 }
311 }
312 break;
313 case GL_TEXTURE_2D_MULTISAMPLE: [[fallthrough]];
314 case GL_INVALID_ENUM:
315 LOG_ERROR(logger, "Texture target #%04x cannot get data uploaded", target);
316 break;
317 }
318 }
319
320 const bool generateMips = (tex.flags & TextureFlags::GenerateMipMaps) != 0;
321 if (generateMips) {
322 glGenerateMipmap(target);
323 }
324}
325
326void Cogs::TexturesGLES30::uploadTextureData(TextureHandle textureHandle,
327 const TextureData& data,
328 uint32_t layer_offset,
329 uint32_t face_offset,
330 uint32_t level_offset)
331{
332 TextureGLES30& texture = this->textures[textureHandle];
333 const GLenum target = texture.target;
334 glBindTexture(target, texture.textureId);
335 uploadTextureData(texture, data, layer_offset, face_offset, level_offset);
336 glBindTexture(target, 0);
337}
338
339
340void Cogs::TexturesGLES30::defineTextureData(TextureGLES30* tex, GLuint textureLevels)
341{
342 const OpenGLES30::DataFormatInfo& fmt = OpenGLES30::DataFormats[size_t(tex->format)];
343 assert(fmt.isTextureFormat);
344
345 switch (tex->target) {
346
347 case GL_TEXTURE_2D:
348 glTexStorage2D(GL_TEXTURE_2D, textureLevels, fmt.internalFormat, tex->width, tex->height);
349 break;
350
351 case GL_TEXTURE_CUBE_MAP:
352 glTexStorage2D(tex->target, textureLevels, fmt.internalFormat, tex->width, tex->height);
353 break;
354
355 case GL_TEXTURE_2D_ARRAY:
356 glTexStorage3D(tex->target, textureLevels, fmt.internalFormat, tex->width, tex->height, tex->depth);
357 break;
358
359 case GL_TEXTURE_3D:
360 glTexStorage3D(tex->target, textureLevels, fmt.internalFormat, tex->width, tex->height, tex->depth);
361 break;
362
363 case GL_TEXTURE_2D_MULTISAMPLE: [[fallthrough]];
364 default:
365 LOG_ERROR(logger, "Texture target #%04x cannot get data uploaded", tex->target);
366 break;
367 }
368}
369
371{
372 if (HandleIsValid(textureHandle)) {
373
374 // Make sure the texture isn't bound
375 for (GLuint i = 0; i < OpenGLES30::maxTexUnits; i++) {
376 if (context->texUnits[i].texture == textureHandle) {
377 if (context->activeTexUnit != i) {
378 context->activeTexUnit = i;
379 glActiveTexture(GL_TEXTURE0 + i);
380 }
381 glBindTexture(context->texUnits[i].target, 0);
382
383 context->texUnits[i].target = GL_TEXTURE_2D;
384 context->texUnits[i].texture = TextureHandle::NoHandle;
385 }
386 }
387
388 // If texture/renderbuffer is external, and NoDelete is not set, we have taken ownership
389 // of the resource and must release it.
390
391 TextureGLES30& texture = textures[textureHandle];
392 if (texture.fbo) {
393 glDeleteFramebuffers(1, &texture.fbo);
394 texture.fbo = 0;
395 }
396 if (texture.renderBuffer) {
397
398 // Don't release it if it is a borrowed renderbuffer
399 if ((texture.target != GL_RENDERBUFFER) || ((texture.flags & TextureFlags::NoDelete) == 0)) {
400 glDeleteRenderbuffers(1, &texture.renderBuffer);
401 }
402 texture.renderBuffer = 0;
403 }
404 // Don't release the texture if it is borrowed
405 if ((texture.textureId != 0) && ((texture.flags & TextureFlags::NoDelete) == 0)) {
406 glDeleteTextures(1, &texture.textureId);
407 }
408 if (texture.textureId != 0) {
409 textureMemoryConsumption -= texture.estimatedByteSize;
410 }
411 texture.textureId = 0;
412
413 textures.removeResource(textureHandle);
414 }
415}
416
417void Cogs::TexturesGLES30::releaseNativeTexture(TextureNativeHandle nativeHandle)
418{
419 GLuint id = (GLuint)(intptr_t)nativeHandle;
420 glDeleteTextures(1, &id);
421}
422
424{
426 LOG_WARNING_ONCE(logger, "loadSamplerState: ES30 does not support border color.");
427 }
428
429 GLuint sampler;
430 glGenSamplers(1, &sampler);
431
432 static const GLenum AddressModes[] = {
433 GL_CLAMP_TO_EDGE,
434 GL_REPEAT,
435 GL_MIRRORED_REPEAT,
436 GL_CLAMP_TO_EDGE
437 };
438 static_assert(sizeof(AddressModes) == sizeof(AddressModes[0]) * Cogs::SamplerState::AddressMode_Size);
439
440 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, AddressModes[state.addressModeS]);
441 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, AddressModes[state.addressModeT]);
442 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, AddressModes[state.addressModeW]);
443
444 static const GLenum ComparisonFunctions[] = {
445 GL_NEVER,
446 GL_LESS,
447 GL_EQUAL,
448 GL_LEQUAL,
449 GL_GREATER,
450 GL_NOTEQUAL,
451 GL_GEQUAL,
452 GL_ALWAYS,
453 };
454 static_assert(sizeof(ComparisonFunctions) == sizeof(ComparisonFunctions[0]) * Cogs::SamplerState::ComparisonFunction_Size);
455
456 if (1 < state.maxAnisotropy) {
457 const GraphicsDeviceCapabilities& deviceCaps = caps->getDeviceCapabilities();
458 float maxAnisotropy = std::min(deviceCaps.MaxAnisotropy, float(state.maxAnisotropy));
459 if (1.f < maxAnisotropy) {
460 glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
461 }
462 }
463
464 switch (state.filter) {
466 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
467 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
468 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_NONE);
469 break;
471 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
472 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
473 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_NONE);
474 break;
476 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
477 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
478 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
479 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC, ComparisonFunctions[state.comparisonFunction]);
480 break;
481
483 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
484 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
485 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
486 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC, ComparisonFunctions[state.comparisonFunction]);
487 break;
488 default:
489 assert(false);
490 }
491
492 return samplers.addResource(SamplerGLES30{ sampler });
493}
494
496{
497 if (HandleIsValid(samplerHandle)) {
498 const SamplerGLES30& sampler = samplers[samplerHandle];
499 glDeleteSamplers(1, &sampler.glName);
500 samplers.removeResource(samplerHandle);
501 }
502}
503
505{
506 if (viewDescription.layerIndex != 0) {
507 LOG_WARNING_ONCE(logger, "Views with nonzero layer index not supported, ignoring");
508 }
509 return views.addResource(viewDescription);
510}
511
513{
514 if (HandleIsValid(handle)) {
515 views.removeResource(handle);
516 }
517}
518
520{
521 if (HandleIsValid(textureHandle)) {
522 const TextureGLES30& tex = textures[textureHandle];
523 if (tex.target == GL_RENDERBUFFER) {
524 return reinterpret_cast<void*>(static_cast<size_t>(tex.renderBuffer));
525 }
526 return reinterpret_cast<void*>(static_cast<size_t>(tex.textureId));
527 }
528 return nullptr;
529}
530
532{
533 TextureGLES30* texture = context->bindTexture(textureHandle);
534 if (texture) {
535 glGenerateMipmap(texture->target);
536 }
537}
538
540{
541 std::vector<TextureHandle> handles;
542 for (TextureGLES30& texture : textures) {
543 handles.push_back(textures.getHandle(texture));
544 }
545 for (TextureHandle& handle : handles) {
546 releaseTexture(handle);
547 }
548}
Log implementation class.
Definition: LogManager.h:140
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:181
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
const GraphicsDeviceCapabilities & getDeviceCapabilities() const override
Gets the device capabilities in a structure.
Contains device capabilities.
Definition: ICapabilities.h:67
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:78
static const Handle_t InvalidHandle
Represents an invalid handle.
Definition: Common.h:81
Encapsulates state for texture sampling in a state object.
Definition: SamplerState.h:12
ComparisonFunction comparisonFunction
Specifies the comparison function to use when applying a comparison sampler.
Definition: SamplerState.h:73
unsigned int maxAnisotropy
Specifies the maximum number of anisotropic samples to use when sampling a texture.
Definition: SamplerState.h:76
AddressMode addressModeW
Specifies the addressing mode along the W axis in texture coordinate space.
Definition: SamplerState.h:67
AddressMode addressModeS
Specifies the addressing mode along the S axis in texture coordinate space.
Definition: SamplerState.h:63
@ Border
Texture color is set to the border color when outside [0, 1] range.
Definition: SamplerState.h:23
@ ComparisonMinMagMipPoint
Comparison filter for depth sample comparisons using point sampling.
Definition: SamplerState.h:38
@ ComparisonMinMagMipLinear
Comparison filter for depth sample comparisons using linear interpolation sampling.
Definition: SamplerState.h:40
@ MinMagMipPoint
Point sampling for both minification and magnification.
Definition: SamplerState.h:33
@ MinMagMipLinear
Linear sampling for both minification and magnification.
Definition: SamplerState.h:35
FilterMode filter
Specifies the filter to use for texture sampling.
Definition: SamplerState.h:70
AddressMode addressModeT
Specifies the addressing mode along the T axis in texture coordinate space.
Definition: SamplerState.h:65
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.
Definition: Flags.h:122
@ NoDelete
The ownership of the underlying texture resource is outside of cogs and cogs will not delete it.
Definition: Flags.h:136
@ GenerateMipMaps
The texture supports automatic mipmap generation performed by the graphics device.
Definition: Flags.h:124
Describes how to fetch data from a texture in shaders.
Definition: ITextures.h:13
uint32_t layerIndex
Index of the first layer (if array) to fetch from.
Definition: ITextures.h:17
void releaseNativeTexture(TextureNativeHandle nativeHandle) override
Release a native texture handle.
void releaseSamplerState(SamplerStateHandle handle)
Release the sampler state with the given handle.
void releaseTexture(TextureHandle textureHandle)
Release the texture with the given textureHandle.
void generateMipmaps(TextureHandle texureHandle)
Use the graphics device to generate mipmaps for the texture with the given texture handle.
void releaseResources()
Release all allocated texture resources.
TextureViewHandle createTextureView(TextureViewDescription &viewDescription) override
Create a texture view used to bind a limited view of the texture data to the rendering pipeline.
void * getNativeHandle(TextureHandle textureHandle) override
Get the device-specific handle (D3D texture pointer, OpenGL texture ID etc) associated with the given...
TextureHandle loadTexture(const TextureDescription &desc, const TextureData *data)
Load a texture from the given description.
void releaseTextureView(const TextureViewHandle &handle) override
Release the given texture view.
SamplerStateHandle loadSamplerState(const SamplerState &state)
Load a sampler state object.