OSDN Git Service

Implement GL_MAX_PROGRAM_TEXEL_OFFSET and GL_MAX_TEXTURE_LOD_BIAS
[android-x86/external-swiftshader.git] / src / Renderer / Sampler.cpp
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "Sampler.hpp"
16
17 #include "Context.hpp"
18 #include "Surface.hpp"
19 #include "PixelRoutine.hpp"
20 #include "Debug.hpp"
21
22 #include <memory.h>
23 #include <string.h>
24
25 namespace sw
26 {
27         FilterType Sampler::maximumTextureFilterQuality = FILTER_LINEAR;
28         MipmapType Sampler::maximumMipmapFilterQuality = MIPMAP_POINT;
29
30         Sampler::State::State()
31         {
32                 memset(this, 0, sizeof(State));
33         }
34
35         Sampler::Sampler()
36         {
37                 // FIXME: Mipmap::init
38                 static const unsigned int zero = 0x00FF00FF;
39
40                 for(int level = 0; level < MIPMAP_LEVELS; level++)
41                 {
42                         Mipmap &mipmap = texture.mipmap[level];
43
44                         memset(&mipmap, 0, sizeof(Mipmap));
45
46                         for(int face = 0; face < 6; face++)
47                         {
48                                 mipmap.buffer[face] = &zero;
49                         }
50                 }
51
52                 externalTextureFormat = FORMAT_NULL;
53                 internalTextureFormat = FORMAT_NULL;
54                 textureType = TEXTURE_NULL;
55
56                 textureFilter = FILTER_LINEAR;
57                 addressingModeU = ADDRESSING_WRAP;
58                 addressingModeV = ADDRESSING_WRAP;
59                 addressingModeW = ADDRESSING_WRAP;
60                 mipmapFilterState = MIPMAP_NONE;
61                 sRGB = false;
62                 gather = false;
63                 highPrecisionFiltering = false;
64
65                 swizzleR = SWIZZLE_RED;
66                 swizzleG = SWIZZLE_GREEN;
67                 swizzleB = SWIZZLE_BLUE;
68                 swizzleA = SWIZZLE_ALPHA;
69
70                 texture.LOD = 0.0f;
71                 exp2LOD = 1.0f;
72
73                 texture.baseLevel = 0;
74                 texture.maxLevel = 1000;
75                 texture.maxLod = MAX_TEXTURE_LOD;
76                 texture.minLod = 0;
77         }
78
79         Sampler::~Sampler()
80         {
81         }
82
83         Sampler::State Sampler::samplerState() const
84         {
85                 State state;
86
87                 if(textureType != TEXTURE_NULL)
88                 {
89                         state.textureType = textureType;
90                         state.textureFormat = internalTextureFormat;
91                         state.textureFilter = getTextureFilter();
92                         state.addressingModeU = getAddressingModeU();
93                         state.addressingModeV = getAddressingModeV();
94                         state.addressingModeW = getAddressingModeW();
95                         state.mipmapFilter = mipmapFilter();
96                         state.sRGB = sRGB && Surface::isSRGBreadable(externalTextureFormat);
97                         state.swizzleR = swizzleR;
98                         state.swizzleG = swizzleG;
99                         state.swizzleB = swizzleB;
100                         state.swizzleA = swizzleA;
101                         state.highPrecisionFiltering = highPrecisionFiltering;
102
103                         #if PERF_PROFILE
104                                 state.compressedFormat = Surface::isCompressed(externalTextureFormat);
105                         #endif
106                 }
107
108                 return state;
109         }
110
111         void Sampler::setTextureLevel(int face, int level, Surface *surface, TextureType type)
112         {
113                 if(surface)
114                 {
115                         Mipmap &mipmap = texture.mipmap[level];
116
117                         mipmap.buffer[face] = surface->lockInternal(0, 0, 0, LOCK_UNLOCKED, PRIVATE);
118
119                         if(face == 0)
120                         {
121                                 externalTextureFormat = surface->getExternalFormat();
122                                 internalTextureFormat = surface->getInternalFormat();
123
124                                 int width = surface->getWidth();
125                                 int height = surface->getHeight();
126                                 int depth = surface->getDepth();
127                                 int pitchP = surface->getInternalPitchP();
128                                 int sliceP = surface->getInternalSliceP();
129
130                                 if(level == 0)
131                                 {
132                                         texture.widthHeightLOD[0] = width * exp2LOD;
133                                         texture.widthHeightLOD[1] = width * exp2LOD;
134                                         texture.widthHeightLOD[2] = height * exp2LOD;
135                                         texture.widthHeightLOD[3] = height * exp2LOD;
136
137                                         texture.widthLOD[0] = width * exp2LOD;
138                                         texture.widthLOD[1] = width * exp2LOD;
139                                         texture.widthLOD[2] = width * exp2LOD;
140                                         texture.widthLOD[3] = width * exp2LOD;
141
142                                         texture.heightLOD[0] = height * exp2LOD;
143                                         texture.heightLOD[1] = height * exp2LOD;
144                                         texture.heightLOD[2] = height * exp2LOD;
145                                         texture.heightLOD[3] = height * exp2LOD;
146
147                                         texture.depthLOD[0] = depth * exp2LOD;
148                                         texture.depthLOD[1] = depth * exp2LOD;
149                                         texture.depthLOD[2] = depth * exp2LOD;
150                                         texture.depthLOD[3] = depth * exp2LOD;
151                                 }
152
153                                 if(Surface::isFloatFormat(internalTextureFormat))
154                                 {
155                                         mipmap.fWidth[0] = (float)width / 65536.0f;
156                                         mipmap.fWidth[1] = (float)width / 65536.0f;
157                                         mipmap.fWidth[2] = (float)width / 65536.0f;
158                                         mipmap.fWidth[3] = (float)width / 65536.0f;
159
160                                         mipmap.fHeight[0] = (float)height / 65536.0f;
161                                         mipmap.fHeight[1] = (float)height / 65536.0f;
162                                         mipmap.fHeight[2] = (float)height / 65536.0f;
163                                         mipmap.fHeight[3] = (float)height / 65536.0f;
164
165                                         mipmap.fDepth[0] = (float)depth / 65536.0f;
166                                         mipmap.fDepth[1] = (float)depth / 65536.0f;
167                                         mipmap.fDepth[2] = (float)depth / 65536.0f;
168                                         mipmap.fDepth[3] = (float)depth / 65536.0f;
169                                 }
170
171                                 short halfTexelU = 0x8000 / width;
172                                 short halfTexelV = 0x8000 / height;
173                                 short halfTexelW = 0x8000 / depth;
174
175                                 mipmap.uHalf[0] = halfTexelU;
176                                 mipmap.uHalf[1] = halfTexelU;
177                                 mipmap.uHalf[2] = halfTexelU;
178                                 mipmap.uHalf[3] = halfTexelU;
179
180                                 mipmap.vHalf[0] = halfTexelV;
181                                 mipmap.vHalf[1] = halfTexelV;
182                                 mipmap.vHalf[2] = halfTexelV;
183                                 mipmap.vHalf[3] = halfTexelV;
184
185                                 mipmap.wHalf[0] = halfTexelW;
186                                 mipmap.wHalf[1] = halfTexelW;
187                                 mipmap.wHalf[2] = halfTexelW;
188                                 mipmap.wHalf[3] = halfTexelW;
189
190                                 mipmap.width[0] = width;
191                                 mipmap.width[1] = width;
192                                 mipmap.width[2] = width;
193                                 mipmap.width[3] = width;
194
195                                 mipmap.height[0] = height;
196                                 mipmap.height[1] = height;
197                                 mipmap.height[2] = height;
198                                 mipmap.height[3] = height;
199
200                                 mipmap.depth[0] = depth;
201                                 mipmap.depth[1] = depth;
202                                 mipmap.depth[2] = depth;
203                                 mipmap.depth[3] = depth;
204
205                                 mipmap.onePitchP[0] = 1;
206                                 mipmap.onePitchP[1] = pitchP;
207                                 mipmap.onePitchP[2] = 1;
208                                 mipmap.onePitchP[3] = pitchP;
209
210                                 mipmap.pitchP[0] = pitchP;
211                                 mipmap.pitchP[1] = pitchP;
212                                 mipmap.pitchP[2] = pitchP;
213                                 mipmap.pitchP[3] = pitchP;
214
215                                 mipmap.sliceP[0] = sliceP;
216                                 mipmap.sliceP[1] = sliceP;
217                                 mipmap.sliceP[2] = sliceP;
218                                 mipmap.sliceP[3] = sliceP;
219
220                                 if(internalTextureFormat == FORMAT_YV12_BT601 ||
221                                    internalTextureFormat == FORMAT_YV12_BT709 ||
222                                    internalTextureFormat == FORMAT_YV12_JFIF)
223                                 {
224                                         unsigned int YStride = pitchP;
225                                         unsigned int YSize = YStride * height;
226                                         unsigned int CStride = align(YStride / 2, 16);
227                                         unsigned int CSize = CStride * height / 2;
228
229                                         mipmap.buffer[1] = (byte*)mipmap.buffer[0] + YSize;
230                                         mipmap.buffer[2] = (byte*)mipmap.buffer[1] + CSize;
231
232                                         texture.mipmap[1].width[0] = width / 2;
233                                         texture.mipmap[1].width[1] = width / 2;
234                                         texture.mipmap[1].width[2] = width / 2;
235                                         texture.mipmap[1].width[3] = width / 2;
236                                         texture.mipmap[1].height[0] = height / 2;
237                                         texture.mipmap[1].height[1] = height / 2;
238                                         texture.mipmap[1].height[2] = height / 2;
239                                         texture.mipmap[1].height[3] = height / 2;
240                                         texture.mipmap[1].onePitchP[0] = 1;
241                                         texture.mipmap[1].onePitchP[1] = CStride;
242                                         texture.mipmap[1].onePitchP[2] = 1;
243                                         texture.mipmap[1].onePitchP[3] = CStride;
244                                 }
245                         }
246                 }
247
248                 textureType = type;
249         }
250
251         void Sampler::setTextureFilter(FilterType textureFilter)
252         {
253                 this->textureFilter = (FilterType)min(textureFilter, maximumTextureFilterQuality);
254         }
255
256         void Sampler::setMipmapFilter(MipmapType mipmapFilter)
257         {
258                 mipmapFilterState = (MipmapType)min(mipmapFilter, maximumMipmapFilterQuality);
259         }
260
261         void Sampler::setGatherEnable(bool enable)
262         {
263                 gather = enable;
264         }
265
266         void Sampler::setAddressingModeU(AddressingMode addressingMode)
267         {
268                 addressingModeU = addressingMode;
269         }
270
271         void Sampler::setAddressingModeV(AddressingMode addressingMode)
272         {
273                 addressingModeV = addressingMode;
274         }
275
276         void Sampler::setAddressingModeW(AddressingMode addressingMode)
277         {
278                 addressingModeW = addressingMode;
279         }
280
281         void Sampler::setReadSRGB(bool sRGB)
282         {
283                 this->sRGB = sRGB;
284         }
285
286         void Sampler::setBorderColor(const Color<float> &borderColor)
287         {
288                 // FIXME: Compact into generic function   // FIXME: Clamp
289                 short r = iround(0xFFFF * borderColor.r);
290                 short g = iround(0xFFFF * borderColor.g);
291                 short b = iround(0xFFFF * borderColor.b);
292                 short a = iround(0xFFFF * borderColor.a);
293
294                 texture.borderColor4[0][0] = texture.borderColor4[0][1] = texture.borderColor4[0][2] = texture.borderColor4[0][3] = r;
295                 texture.borderColor4[1][0] = texture.borderColor4[1][1] = texture.borderColor4[1][2] = texture.borderColor4[1][3] = g;
296                 texture.borderColor4[2][0] = texture.borderColor4[2][1] = texture.borderColor4[2][2] = texture.borderColor4[2][3] = b;
297                 texture.borderColor4[3][0] = texture.borderColor4[3][1] = texture.borderColor4[3][2] = texture.borderColor4[3][3] = a;
298
299                 texture.borderColorF[0][0] = texture.borderColorF[0][1] = texture.borderColorF[0][2] = texture.borderColorF[0][3] = borderColor.r;
300                 texture.borderColorF[1][0] = texture.borderColorF[1][1] = texture.borderColorF[1][2] = texture.borderColorF[1][3] = borderColor.g;
301                 texture.borderColorF[2][0] = texture.borderColorF[2][1] = texture.borderColorF[2][2] = texture.borderColorF[2][3] = borderColor.b;
302                 texture.borderColorF[3][0] = texture.borderColorF[3][1] = texture.borderColorF[3][2] = texture.borderColorF[3][3] = borderColor.a;
303         }
304
305         void Sampler::setMaxAnisotropy(float maxAnisotropy)
306         {
307                 texture.maxAnisotropy = maxAnisotropy;
308         }
309
310         void Sampler::setHighPrecisionFiltering(bool highPrecisionFiltering)
311         {
312                 this->highPrecisionFiltering = highPrecisionFiltering;
313         }
314
315         void Sampler::setSwizzleR(SwizzleType swizzleR)
316         {
317                 this->swizzleR = swizzleR;
318         }
319
320         void Sampler::setSwizzleG(SwizzleType swizzleG)
321         {
322                 this->swizzleG = swizzleG;
323         }
324
325         void Sampler::setSwizzleB(SwizzleType swizzleB)
326         {
327                 this->swizzleB = swizzleB;
328         }
329
330         void Sampler::setSwizzleA(SwizzleType swizzleA)
331         {
332                 this->swizzleA = swizzleA;
333         }
334
335         void Sampler::setBaseLevel(int baseLevel)
336         {
337                 texture.baseLevel = baseLevel;
338         }
339
340         void Sampler::setMaxLevel(int maxLevel)
341         {
342                 texture.maxLevel = maxLevel;
343         }
344
345         void Sampler::setMinLod(float minLod)
346         {
347                 texture.minLod = clamp(minLod, 0.0f, (float)(MAX_TEXTURE_LOD));
348         }
349
350         void Sampler::setMaxLod(float maxLod)
351         {
352                 texture.maxLod = clamp(maxLod, 0.0f, (float)(MAX_TEXTURE_LOD));
353         }
354
355         void Sampler::setFilterQuality(FilterType maximumFilterQuality)
356         {
357                 Sampler::maximumTextureFilterQuality = maximumFilterQuality;
358         }
359
360         void Sampler::setMipmapQuality(MipmapType maximumFilterQuality)
361         {
362                 Sampler::maximumMipmapFilterQuality = maximumFilterQuality;
363         }
364
365         void Sampler::setMipmapLOD(float LOD)
366         {
367                 texture.LOD = LOD;
368                 exp2LOD = exp2(LOD);
369         }
370
371         bool Sampler::hasTexture() const
372         {
373                 return textureType != TEXTURE_NULL;
374         }
375
376         bool Sampler::hasUnsignedTexture() const
377         {
378                 return Surface::isUnsignedComponent(internalTextureFormat, 0) &&
379                        Surface::isUnsignedComponent(internalTextureFormat, 1) &&
380                        Surface::isUnsignedComponent(internalTextureFormat, 2) &&
381                        Surface::isUnsignedComponent(internalTextureFormat, 3);
382         }
383
384         bool Sampler::hasCubeTexture() const
385         {
386                 return textureType == TEXTURE_CUBE;
387         }
388
389         bool Sampler::hasVolumeTexture() const
390         {
391                 return textureType == TEXTURE_3D || textureType == TEXTURE_2D_ARRAY;
392         }
393
394         const Texture &Sampler::getTextureData()
395         {
396                 return texture;
397         }
398
399         MipmapType Sampler::mipmapFilter() const
400         {
401                 if(mipmapFilterState != MIPMAP_NONE)
402                 {
403                         for(int i = 1; i < MIPMAP_LEVELS; i++)
404                         {
405                                 if(texture.mipmap[0].buffer[0] != texture.mipmap[i].buffer[0])
406                                 {
407                                         return mipmapFilterState;
408                                 }
409                         }
410                 }
411
412                 // Only one mipmap level
413                 return MIPMAP_NONE;
414         }
415
416         TextureType Sampler::getTextureType() const
417         {
418                 return textureType;
419         }
420
421         FilterType Sampler::getTextureFilter() const
422         {
423                 // Don't filter 1x1 textures.
424                 if(texture.mipmap[0].width[0] == 1 && texture.mipmap[0].height[0] == 1 && texture.mipmap[0].depth[0] == 1)
425                 {
426                         if(mipmapFilter() == MIPMAP_NONE)
427                         {
428                                 return FILTER_POINT;
429                         }
430                 }
431
432                 FilterType filter = textureFilter;
433
434                 if(gather && Surface::componentCount(internalTextureFormat) == 1)
435                 {
436                         filter = FILTER_GATHER;
437                 }
438
439                 if(textureType != TEXTURE_2D || texture.maxAnisotropy == 1.0f)
440                 {
441                         return (FilterType)min(filter, FILTER_LINEAR);
442                 }
443
444                 return filter;
445         }
446
447         AddressingMode Sampler::getAddressingModeU() const
448         {
449                 if(hasCubeTexture())
450                 {
451                         return ADDRESSING_CLAMP;
452                 }
453
454                 return addressingModeU;
455         }
456
457         AddressingMode Sampler::getAddressingModeV() const
458         {
459                 if(hasCubeTexture())
460                 {
461                         return ADDRESSING_CLAMP;
462                 }
463
464                 return addressingModeV;
465         }
466
467         AddressingMode Sampler::getAddressingModeW() const
468         {
469                 if(hasCubeTexture())
470                 {
471                         return ADDRESSING_CLAMP;
472                 }
473
474                 if(textureType == TEXTURE_2D_ARRAY || textureType == TEXTURE_2D)
475                 {
476                         return ADDRESSING_LAYER;
477                 }
478
479                 return addressingModeW;
480         }
481 }