blob: 0df34c781f836024d0a04d1166078fb1c6ba6e81 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// 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// utilities.cpp: Conversion functions and other utility routines.
16
17#include "utilities.h"
18
19#include "mathutil.h"
20#include "Context.h"
21#include "common/debug.h"
22
23#include <limits>
24#include <stdio.h>
25
26namespace es1
27{
28 bool IsCompressed(GLenum format)
29 {
30 return format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
31 format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
32 format == GL_ETC1_RGB8_OES;
33 }
34
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -050035 bool IsSizedInternalFormat(GLint internalformat)
36 {
37 switch(internalformat)
38 {
39 case GL_ALPHA8_EXT:
40 case GL_LUMINANCE8_ALPHA8_EXT:
41 case GL_LUMINANCE8_EXT:
42 case GL_RGBA4_OES:
43 case GL_RGB5_A1_OES:
44 case GL_RGB565_OES:
45 case GL_RGB8_OES:
46 case GL_RGBA8_OES:
47 case GL_BGRA8_EXT: // GL_APPLE_texture_format_BGRA8888
48 case GL_DEPTH_COMPONENT16_OES:
49 case GL_STENCIL_INDEX8_OES:
50 case GL_DEPTH24_STENCIL8_OES:
51 return true;
52 default:
53 return false;
54 }
55 }
56
57 GLenum ValidateSubImageParams(bool compressed, bool copy, GLenum target, GLint level, GLint xoffset, GLint yoffset,
58 GLsizei width, GLsizei height, GLenum format, GLenum type, Texture *texture)
59 {
60 if(!texture)
61 {
62 return GL_INVALID_OPERATION;
63 }
64
65 GLenum sizedInternalFormat = texture->getFormat(target, level);
66
67 if(compressed)
68 {
69 if(format != sizedInternalFormat)
70 {
71 return GL_INVALID_OPERATION;
72 }
73 }
74 else if(!copy) // CopyTexSubImage doesn't have format/type parameters.
75 {
76 GLenum validationError = ValidateTextureFormatType(format, type, sizedInternalFormat, target);
77 if(validationError != GL_NO_ERROR)
78 {
79 return validationError;
80 }
81 }
82
83 if(compressed)
84 {
85 if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
86 (height % 4 != 0 && height != texture->getHeight(target, 0)))
87 {
88 return GL_INVALID_OPERATION;
89 }
90 }
91
92 if(xoffset + width > texture->getWidth(target, level) ||
93 yoffset + height > texture->getHeight(target, level))
94 {
95 return GL_INVALID_VALUE;
96 }
97
98 return GL_NO_ERROR;
99 }
100
Nicolas Capens0bac2852016-05-07 06:09:58 -0400101 bool IsDepthTexture(GLenum format)
102 {
103 return format == GL_DEPTH_STENCIL_OES;
104 }
105
106 bool IsStencilTexture(GLenum format)
107 {
108 return format == GL_DEPTH_STENCIL_OES;
109 }
110
111 bool IsCubemapTextureTarget(GLenum target)
112 {
113 return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES);
114 }
115
116 int CubeFaceIndex(GLenum cubeFace)
117 {
118 switch(cubeFace)
119 {
120 case GL_TEXTURE_CUBE_MAP_OES:
121 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES: return 0;
122 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES: return 1;
123 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES: return 2;
124 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES: return 3;
125 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES: return 4;
126 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES: return 5;
127 default: UNREACHABLE(cubeFace); return 0;
128 }
129 }
130
131 bool IsTextureTarget(GLenum target)
132 {
133 return target == GL_TEXTURE_2D;
134 }
135
136 // Verify that format/type are one of the combinations from table 3.4.
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500137 GLenum ValidateTextureFormatType(GLenum format, GLenum type, GLint internalformat, GLenum target)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400138 {
139 switch(type)
140 {
141 case GL_UNSIGNED_BYTE:
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500142 case GL_UNSIGNED_SHORT_4_4_4_4:
143 case GL_UNSIGNED_SHORT_5_5_5_1:
144 case GL_UNSIGNED_SHORT_5_6_5:
145 case GL_UNSIGNED_INT_24_8_OES: // GL_OES_packed_depth_stencil
146 break;
147 default:
148 return GL_INVALID_ENUM;
149 }
150
151 switch(format)
152 {
153 case GL_ALPHA:
154 case GL_RGB:
155 case GL_RGBA:
156 case GL_LUMINANCE:
157 case GL_LUMINANCE_ALPHA:
158 case GL_BGRA_EXT: // GL_EXT_texture_format_BGRA8888
159 break;
160 case GL_DEPTH_STENCIL_OES: // GL_OES_packed_depth_stencil (GL_DEPTH_STENCIL_OES)
161 switch(target)
162 {
163 case GL_TEXTURE_2D:
164 break;
165 default:
166 return GL_INVALID_OPERATION;
167 }
168 break;
169 default:
170 return GL_INVALID_ENUM;
171 }
172
173 if((GLenum)internalformat != format)
174 {
175 if(gl::IsUnsizedInternalFormat(internalformat))
176 {
177 return GL_INVALID_OPERATION;
178 }
179
180 if(!IsSizedInternalFormat(internalformat))
181 {
182 return GL_INVALID_VALUE;
183 }
184 }
185
186 if((GLenum)internalformat == format)
187 {
188 // Validate format, type, and unsized internalformat combinations [OpenGL ES 1.1 Table 3.3]
Nicolas Capens0bac2852016-05-07 06:09:58 -0400189 switch(format)
190 {
191 case GL_RGBA:
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500192 switch(type)
193 {
194 case GL_UNSIGNED_BYTE:
195 case GL_UNSIGNED_SHORT_4_4_4_4:
196 case GL_UNSIGNED_SHORT_5_5_5_1:
197 break;
198 default:
199 return GL_INVALID_OPERATION;
200 }
201 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400202 case GL_RGB:
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500203 switch(type)
204 {
205 case GL_UNSIGNED_BYTE:
206 case GL_UNSIGNED_SHORT_5_6_5:
207 break;
208 default:
209 return GL_INVALID_OPERATION;
210 }
211 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400212 case GL_LUMINANCE_ALPHA:
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500213 case GL_LUMINANCE:
214 case GL_ALPHA:
215 switch(type)
216 {
217 case GL_UNSIGNED_BYTE:
218 break;
219 default:
220 return GL_INVALID_OPERATION;
221 }
222 break;
223 case GL_DEPTH_STENCIL_OES:
224 switch(type)
225 {
226 case GL_UNSIGNED_INT_24_8_OES: // GL_OES_packed_depth_stencil
227 break;
228 default:
229 return GL_INVALID_OPERATION;
230 }
231 break;
232 case GL_BGRA_EXT:
233 if(type != GL_UNSIGNED_BYTE) // GL_APPLE_texture_format_BGRA8888 / GL_EXT_texture_format_BGRA8888
234 {
235 return GL_INVALID_OPERATION;
236 }
237 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400238 default:
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500239 UNREACHABLE(format);
240 return GL_INVALID_ENUM;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400241 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400242
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500243 return GL_NO_ERROR;
244 }
245
246 // Validate format, type, and sized internalformat combinations [OpenGL ES 3.0 Table 3.2]
247 bool validSizedInternalformat = false;
248 #define VALIDATE_INTERNALFORMAT(...) { GLint validInternalformats[] = {__VA_ARGS__}; for(GLint v : validInternalformats) {if(internalformat == v) validSizedInternalformat = true;} } break;
249
250 switch(format)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400251 {
Nicolas Capens2b6a8da2016-06-29 00:33:52 -0400252 case GL_RGBA:
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500253 switch(type)
254 {
255 case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_RGBA8_OES, GL_RGB5_A1_OES, GL_RGBA4_OES)
256 case GL_UNSIGNED_SHORT_4_4_4_4: VALIDATE_INTERNALFORMAT(GL_RGBA4_OES)
257 case GL_UNSIGNED_SHORT_5_5_5_1: VALIDATE_INTERNALFORMAT(GL_RGB5_A1_OES)
258 default: return GL_INVALID_OPERATION;
259 }
260 break;
261 case GL_RGB:
262 switch(type)
263 {
264 case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_RGB8_OES, GL_RGB565_OES)
265 case GL_UNSIGNED_SHORT_5_6_5: VALIDATE_INTERNALFORMAT(GL_RGB565_OES)
266 default: return GL_INVALID_OPERATION;
267 }
268 break;
269 case GL_DEPTH_STENCIL_OES:
270 switch(type)
271 {
272 case GL_UNSIGNED_INT_24_8_OES: VALIDATE_INTERNALFORMAT(GL_DEPTH24_STENCIL8_OES)
273 default: return GL_INVALID_OPERATION;
274 }
275 break;
276 case GL_LUMINANCE_ALPHA:
277 switch(type)
278 {
279 case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_LUMINANCE8_ALPHA8_EXT)
280 default:
281 return GL_INVALID_OPERATION;
282 }
283 break;
284 case GL_LUMINANCE:
285 switch(type)
286 {
287 case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_LUMINANCE8_EXT)
288 default:
289 return GL_INVALID_OPERATION;
290 }
291 break;
292 case GL_ALPHA:
293 switch(type)
294 {
295 case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_ALPHA8_EXT)
296 default:
297 return GL_INVALID_OPERATION;
298 }
299 break;
300 case GL_BGRA_EXT: // GL_APPLE_texture_format_BGRA8888
301 switch(type)
302 {
303 case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_BGRA8_EXT)
304 default: return GL_INVALID_OPERATION;
305 }
306 break;
307 default:
308 UNREACHABLE(format);
309 return GL_INVALID_ENUM;
310 }
311
312 #undef VALIDATE_INTERNALFORMAT
313
314 if(!validSizedInternalformat)
315 {
316 return GL_INVALID_OPERATION;
317 }
318
319 return GL_NO_ERROR;
320 }
321
322 bool IsColorRenderable(GLint internalformat)
323 {
324 switch(internalformat)
325 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400326 case GL_RGBA4_OES:
327 case GL_RGB5_A1_OES:
328 case GL_RGB565_OES:
329 case GL_RGB8_OES:
330 case GL_RGBA8_OES:
331 return true;
332 case GL_DEPTH_COMPONENT16_OES:
333 case GL_STENCIL_INDEX8_OES:
334 case GL_DEPTH24_STENCIL8_OES:
335 return false;
336 default:
337 UNIMPLEMENTED();
338 }
339
340 return false;
341 }
342
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500343 bool IsDepthRenderable(GLint internalformat)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400344 {
345 switch(internalformat)
346 {
347 case GL_DEPTH_COMPONENT16_OES:
348 case GL_DEPTH24_STENCIL8_OES:
349 return true;
350 case GL_STENCIL_INDEX8_OES:
351 case GL_RGBA4_OES:
352 case GL_RGB5_A1_OES:
353 case GL_RGB565_OES:
354 case GL_RGB8_OES:
355 case GL_RGBA8_OES:
356 return false;
357 default:
358 UNIMPLEMENTED();
359 }
360
361 return false;
362 }
363
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500364 bool IsStencilRenderable(GLint internalformat)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400365 {
366 switch(internalformat)
367 {
368 case GL_STENCIL_INDEX8_OES:
369 case GL_DEPTH24_STENCIL8_OES:
370 return true;
371 case GL_RGBA4_OES:
372 case GL_RGB5_A1_OES:
373 case GL_RGB565_OES:
374 case GL_RGB8_OES:
375 case GL_RGBA8_OES:
376 case GL_DEPTH_COMPONENT16_OES:
377 return false;
378 default:
379 UNIMPLEMENTED();
380 }
381
382 return false;
383 }
384
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500385 GLuint GetAlphaSize(GLint internalformat)
386 {
387 switch(internalformat)
388 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500389 case GL_NONE_OES: return 0;
390 case GL_RGBA4_OES: return 4;
391 case GL_RGB5_A1_OES: return 1;
392 case GL_RGB565_OES: return 0;
393 case GL_RGB8_OES: return 0;
394 case GL_RGBA8_OES: return 8;
395 case GL_BGRA8_EXT: return 8;
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500396 default:
397 // UNREACHABLE(internalformat);
398 return 0;
399 }
400 }
401
402 GLuint GetRedSize(GLint internalformat)
403 {
404 switch(internalformat)
405 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500406 case GL_NONE_OES: return 0;
407 case GL_RGBA4_OES: return 4;
408 case GL_RGB5_A1_OES: return 5;
409 case GL_RGB565_OES: return 5;
410 case GL_RGB8_OES: return 8;
411 case GL_RGBA8_OES: return 8;
412 case GL_BGRA8_EXT: return 8;
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500413 default:
414 // UNREACHABLE(internalformat);
415 return 0;
416 }
417 }
418
419 GLuint GetGreenSize(GLint internalformat)
420 {
421 switch(internalformat)
422 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500423 case GL_NONE_OES: return 0;
424 case GL_RGBA4_OES: return 4;
425 case GL_RGB5_A1_OES: return 5;
426 case GL_RGB565_OES: return 6;
427 case GL_RGB8_OES: return 8;
428 case GL_RGBA8_OES: return 8;
429 case GL_BGRA8_EXT: return 8;
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500430 default:
431 // UNREACHABLE(internalformat);
432 return 0;
433 }
434 }
435
436 GLuint GetBlueSize(GLint internalformat)
437 {
438 switch(internalformat)
439 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500440 case GL_NONE_OES: return 0;
441 case GL_RGBA4_OES: return 4;
442 case GL_RGB5_A1_OES: return 5;
443 case GL_RGB565_OES: return 5;
444 case GL_RGB8_OES: return 8;
445 case GL_RGBA8_OES: return 8;
446 case GL_BGRA8_EXT: return 8;
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500447 default:
448 // UNREACHABLE(internalformat);
449 return 0;
450 }
451 }
452
453 GLuint GetDepthSize(GLint internalformat)
454 {
455 switch(internalformat)
456 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500457 case GL_STENCIL_INDEX8_OES: return 0;
458 case GL_DEPTH_COMPONENT16_OES: return 16;
459 case GL_DEPTH24_STENCIL8_OES: return 24;
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500460 default:
461 // UNREACHABLE(internalformat);
462 return 0;
463 }
464 }
465
466 GLuint GetStencilSize(GLint internalformat)
467 {
468 switch(internalformat)
469 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500470 case GL_STENCIL_INDEX8_OES: return 8;
471 case GL_DEPTH_COMPONENT16_OES: return 0;
472 case GL_DEPTH24_STENCIL8_OES: return 8;
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500473 default:
474 // UNREACHABLE(internalformat);
475 return 0;
476 }
477 }
478
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500479 bool IsAlpha(GLint internalformat)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400480 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500481 switch(internalformat)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400482 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500483 case GL_ALPHA8_EXT:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400484 return true;
485 default:
486 return false;
487 }
488 }
489
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500490 bool IsRGB(GLint internalformat)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400491 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500492 switch(internalformat)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400493 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500494 case GL_LUMINANCE8_EXT:
495 case GL_RGB565_OES:
496 case GL_RGB8_OES:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400497 case SW_YV12_BT601:
498 case SW_YV12_BT709:
499 case SW_YV12_JFIF:
500 return true;
501 default:
502 return false;
503 }
504 }
505
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500506 bool IsRGBA(GLint internalformat)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400507 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500508 switch(internalformat)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400509 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500510 case GL_LUMINANCE8_ALPHA8_EXT:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400511 case GL_RGBA:
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500512 case GL_BGRA8_EXT: // GL_EXT_texture_format_BGRA8888
513 case GL_RGBA4_OES:
514 case GL_RGB5_A1_OES:
515 case GL_RGBA8_OES:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400516 return true;
517 default:
518 return false;
519 }
520 }
521}
522
523namespace es2sw
524{
525 sw::DepthCompareMode ConvertDepthComparison(GLenum comparison)
526 {
527 switch(comparison)
528 {
529 case GL_NEVER: return sw::DEPTH_NEVER;
530 case GL_ALWAYS: return sw::DEPTH_ALWAYS;
531 case GL_LESS: return sw::DEPTH_LESS;
532 case GL_LEQUAL: return sw::DEPTH_LESSEQUAL;
533 case GL_EQUAL: return sw::DEPTH_EQUAL;
534 case GL_GREATER: return sw::DEPTH_GREATER;
535 case GL_GEQUAL: return sw::DEPTH_GREATEREQUAL;
536 case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL;
537 default: UNREACHABLE(comparison);
538 }
539
540 return sw::DEPTH_ALWAYS;
541 }
542
543 sw::StencilCompareMode ConvertStencilComparison(GLenum comparison)
544 {
545 switch(comparison)
546 {
547 case GL_NEVER: return sw::STENCIL_NEVER;
548 case GL_ALWAYS: return sw::STENCIL_ALWAYS;
549 case GL_LESS: return sw::STENCIL_LESS;
550 case GL_LEQUAL: return sw::STENCIL_LESSEQUAL;
551 case GL_EQUAL: return sw::STENCIL_EQUAL;
552 case GL_GREATER: return sw::STENCIL_GREATER;
553 case GL_GEQUAL: return sw::STENCIL_GREATEREQUAL;
554 case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL;
555 default: UNREACHABLE(comparison);
556 }
557
558 return sw::STENCIL_ALWAYS;
559 }
560
561 sw::AlphaCompareMode ConvertAlphaComparison(GLenum comparison)
562 {
563 switch(comparison)
564 {
565 case GL_NEVER: return sw::ALPHA_NEVER;
566 case GL_ALWAYS: return sw::ALPHA_ALWAYS;
567 case GL_LESS: return sw::ALPHA_LESS;
568 case GL_LEQUAL: return sw::ALPHA_LESSEQUAL;
569 case GL_EQUAL: return sw::ALPHA_EQUAL;
570 case GL_GREATER: return sw::ALPHA_GREATER;
571 case GL_GEQUAL: return sw::ALPHA_GREATEREQUAL;
572 case GL_NOTEQUAL: return sw::ALPHA_NOTEQUAL;
573 default: UNREACHABLE(comparison);
574 }
575
576 return sw::ALPHA_ALWAYS;
577 }
578
579 sw::Color<float> ConvertColor(es1::Color color)
580 {
581 return sw::Color<float>(color.red, color.green, color.blue, color.alpha);
582 }
583
584 sw::BlendFactor ConvertBlendFunc(GLenum blend)
585 {
586 switch(blend)
587 {
588 case GL_ZERO: return sw::BLEND_ZERO;
589 case GL_ONE: return sw::BLEND_ONE;
590 case GL_SRC_COLOR: return sw::BLEND_SOURCE;
591 case GL_ONE_MINUS_SRC_COLOR: return sw::BLEND_INVSOURCE;
592 case GL_DST_COLOR: return sw::BLEND_DEST;
593 case GL_ONE_MINUS_DST_COLOR: return sw::BLEND_INVDEST;
594 case GL_SRC_ALPHA: return sw::BLEND_SOURCEALPHA;
595 case GL_ONE_MINUS_SRC_ALPHA: return sw::BLEND_INVSOURCEALPHA;
596 case GL_DST_ALPHA: return sw::BLEND_DESTALPHA;
597 case GL_ONE_MINUS_DST_ALPHA: return sw::BLEND_INVDESTALPHA;
598 case GL_SRC_ALPHA_SATURATE: return sw::BLEND_SRCALPHASAT;
599 default: UNREACHABLE(blend);
600 }
601
602 return sw::BLEND_ZERO;
603 }
604
605 sw::BlendOperation ConvertBlendOp(GLenum blendOp)
606 {
607 switch(blendOp)
608 {
609 case GL_FUNC_ADD_OES: return sw::BLENDOP_ADD;
610 case GL_FUNC_SUBTRACT_OES: return sw::BLENDOP_SUB;
611 case GL_FUNC_REVERSE_SUBTRACT_OES: return sw::BLENDOP_INVSUB;
612 case GL_MIN_EXT: return sw::BLENDOP_MIN;
613 case GL_MAX_EXT: return sw::BLENDOP_MAX;
614 default: UNREACHABLE(blendOp);
615 }
616
617 return sw::BLENDOP_ADD;
618 }
619
620 sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation)
621 {
622 switch(logicalOperation)
623 {
624 case GL_CLEAR: return sw::LOGICALOP_CLEAR;
625 case GL_SET: return sw::LOGICALOP_SET;
626 case GL_COPY: return sw::LOGICALOP_COPY;
627 case GL_COPY_INVERTED: return sw::LOGICALOP_COPY_INVERTED;
628 case GL_NOOP: return sw::LOGICALOP_NOOP;
629 case GL_INVERT: return sw::LOGICALOP_INVERT;
630 case GL_AND: return sw::LOGICALOP_AND;
631 case GL_NAND: return sw::LOGICALOP_NAND;
632 case GL_OR: return sw::LOGICALOP_OR;
633 case GL_NOR: return sw::LOGICALOP_NOR;
634 case GL_XOR: return sw::LOGICALOP_XOR;
635 case GL_EQUIV: return sw::LOGICALOP_EQUIV;
636 case GL_AND_REVERSE: return sw::LOGICALOP_AND_REVERSE;
637 case GL_AND_INVERTED: return sw::LOGICALOP_AND_INVERTED;
638 case GL_OR_REVERSE: return sw::LOGICALOP_OR_REVERSE;
639 case GL_OR_INVERTED: return sw::LOGICALOP_OR_INVERTED;
640 default: UNREACHABLE(logicalOperation);
641 }
642
643 return sw::LOGICALOP_COPY;
644 }
645
646 sw::StencilOperation ConvertStencilOp(GLenum stencilOp)
647 {
648 switch(stencilOp)
649 {
650 case GL_ZERO: return sw::OPERATION_ZERO;
651 case GL_KEEP: return sw::OPERATION_KEEP;
652 case GL_REPLACE: return sw::OPERATION_REPLACE;
653 case GL_INCR: return sw::OPERATION_INCRSAT;
654 case GL_DECR: return sw::OPERATION_DECRSAT;
655 case GL_INVERT: return sw::OPERATION_INVERT;
656 case GL_INCR_WRAP_OES: return sw::OPERATION_INCR;
657 case GL_DECR_WRAP_OES: return sw::OPERATION_DECR;
658 default: UNREACHABLE(stencilOp);
659 }
660
661 return sw::OPERATION_KEEP;
662 }
663
664 sw::AddressingMode ConvertTextureWrap(GLenum wrap)
665 {
666 switch(wrap)
667 {
668 case GL_REPEAT: return sw::ADDRESSING_WRAP;
669 case GL_CLAMP_TO_EDGE: return sw::ADDRESSING_CLAMP;
670 case GL_MIRRORED_REPEAT_OES: return sw::ADDRESSING_MIRROR;
671 default: UNREACHABLE(wrap);
672 }
673
674 return sw::ADDRESSING_WRAP;
675 }
676
677 sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace)
678 {
679 switch(cullFace)
680 {
681 case GL_FRONT:
682 return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE);
683 case GL_BACK:
684 return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE);
685 case GL_FRONT_AND_BACK:
686 return sw::CULL_NONE; // culling will be handled during draw
687 default: UNREACHABLE(cullFace);
688 }
689
690 return sw::CULL_COUNTERCLOCKWISE;
691 }
692
693 unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha)
694 {
695 return (red ? 0x00000001 : 0) |
696 (green ? 0x00000002 : 0) |
697 (blue ? 0x00000004 : 0) |
698 (alpha ? 0x00000008 : 0);
699 }
700
701 sw::MipmapType ConvertMipMapFilter(GLenum minFilter)
702 {
703 switch(minFilter)
704 {
705 case GL_NEAREST:
706 case GL_LINEAR:
707 return sw::MIPMAP_NONE;
708 break;
709 case GL_NEAREST_MIPMAP_NEAREST:
710 case GL_LINEAR_MIPMAP_NEAREST:
711 return sw::MIPMAP_POINT;
712 break;
713 case GL_NEAREST_MIPMAP_LINEAR:
714 case GL_LINEAR_MIPMAP_LINEAR:
715 return sw::MIPMAP_LINEAR;
716 break;
717 default:
718 UNREACHABLE(minFilter);
719 return sw::MIPMAP_NONE;
720 }
721 }
722
723 sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy)
724 {
725 if(maxAnisotropy > 1.0f)
726 {
727 return sw::FILTER_ANISOTROPIC;
728 }
729
730 sw::FilterType magFilterType = sw::FILTER_POINT;
731 switch(magFilter)
732 {
733 case GL_NEAREST: magFilterType = sw::FILTER_POINT; break;
734 case GL_LINEAR: magFilterType = sw::FILTER_LINEAR; break;
735 default: UNREACHABLE(magFilter);
736 }
737
738 switch(minFilter)
739 {
740 case GL_NEAREST:
741 case GL_NEAREST_MIPMAP_NEAREST:
742 case GL_NEAREST_MIPMAP_LINEAR:
743 return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR;
744 case GL_LINEAR:
745 case GL_LINEAR_MIPMAP_NEAREST:
746 case GL_LINEAR_MIPMAP_LINEAR:
747 return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_MIN_LINEAR_MAG_POINT : sw::FILTER_LINEAR;
748 default:
749 UNREACHABLE(minFilter);
750 return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR;
751 }
752 }
753
754 bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, GLenum elementType, sw::DrawType &drawType, int &primitiveCount)
755 {
756 switch(primitiveType)
757 {
758 case GL_POINTS:
759 drawType = sw::DRAW_POINTLIST;
760 primitiveCount = elementCount;
761 break;
762 case GL_LINES:
763 drawType = sw::DRAW_LINELIST;
764 primitiveCount = elementCount / 2;
765 break;
766 case GL_LINE_LOOP:
767 drawType = sw::DRAW_LINELOOP;
768 primitiveCount = elementCount;
769 break;
770 case GL_LINE_STRIP:
771 drawType = sw::DRAW_LINESTRIP;
772 primitiveCount = elementCount - 1;
773 break;
774 case GL_TRIANGLES:
775 drawType = sw::DRAW_TRIANGLELIST;
776 primitiveCount = elementCount / 3;
777 break;
778 case GL_TRIANGLE_STRIP:
779 drawType = sw::DRAW_TRIANGLESTRIP;
780 primitiveCount = elementCount - 2;
781 break;
782 case GL_TRIANGLE_FAN:
783 drawType = sw::DRAW_TRIANGLEFAN;
784 primitiveCount = elementCount - 2;
785 break;
786 default:
787 return false;
788 }
789
790 sw::DrawType elementSize;
791 switch(elementType)
792 {
Nicolas Capens3e5f6fd2018-02-26 17:47:06 -0500793 case GL_NONE_OES: elementSize = sw::DRAW_NONINDEXED; break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400794 case GL_UNSIGNED_BYTE: elementSize = sw::DRAW_INDEXED8; break;
795 case GL_UNSIGNED_SHORT: elementSize = sw::DRAW_INDEXED16; break;
796 case GL_UNSIGNED_INT: elementSize = sw::DRAW_INDEXED32; break;
797 default: return false;
798 }
799
800 drawType = sw::DrawType(drawType | elementSize);
801
802 return true;
803 }
804
Nicolas Capens0bac2852016-05-07 06:09:58 -0400805 sw::TextureStage::StageOperation ConvertCombineOperation(GLenum operation)
806 {
807 switch(operation)
808 {
809 case GL_REPLACE: return sw::TextureStage::STAGE_SELECTARG1;
810 case GL_MODULATE: return sw::TextureStage::STAGE_MODULATE;
811 case GL_ADD: return sw::TextureStage::STAGE_ADD;
812 case GL_ADD_SIGNED: return sw::TextureStage::STAGE_ADDSIGNED;
813 case GL_INTERPOLATE: return sw::TextureStage::STAGE_LERP;
814 case GL_SUBTRACT: return sw::TextureStage::STAGE_SUBTRACT;
815 case GL_DOT3_RGB: return sw::TextureStage::STAGE_DOT3;
816 case GL_DOT3_RGBA: return sw::TextureStage::STAGE_DOT3;
817 default: UNREACHABLE(operation); return sw::TextureStage::STAGE_SELECTARG1;
818 }
819 }
820
821 sw::TextureStage::SourceArgument ConvertSourceArgument(GLenum argument)
822 {
823 switch(argument)
824 {
825 case GL_TEXTURE: return sw::TextureStage::SOURCE_TEXTURE;
826 case GL_CONSTANT: return sw::TextureStage::SOURCE_CONSTANT;
827 case GL_PRIMARY_COLOR: return sw::TextureStage::SOURCE_DIFFUSE;
828 case GL_PREVIOUS: return sw::TextureStage::SOURCE_CURRENT;
829 default: UNREACHABLE(argument); return sw::TextureStage::SOURCE_CURRENT;
830 }
831 }
832
833 sw::TextureStage::ArgumentModifier ConvertSourceOperand(GLenum operand)
834 {
835 switch(operand)
836 {
837 case GL_SRC_COLOR: return sw::TextureStage::MODIFIER_COLOR;
838 case GL_ONE_MINUS_SRC_COLOR: return sw::TextureStage::MODIFIER_INVCOLOR;
839 case GL_SRC_ALPHA: return sw::TextureStage::MODIFIER_ALPHA;
840 case GL_ONE_MINUS_SRC_ALPHA: return sw::TextureStage::MODIFIER_INVALPHA;
841 default: UNREACHABLE(operand); return sw::TextureStage::MODIFIER_COLOR;
842 }
843 }
844}
845
846namespace sw2es
847{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400848 GLenum ConvertBackBufferFormat(sw::Format format)
849 {
850 switch(format)
851 {
852 case sw::FORMAT_A4R4G4B4: return GL_RGBA4_OES;
853 case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES;
854 case sw::FORMAT_A8B8G8R8: return GL_RGBA8_OES;
855 case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1_OES;
856 case sw::FORMAT_R5G6B5: return GL_RGB565_OES;
857 case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES;
858 case sw::FORMAT_X8B8G8R8: return GL_RGB8_OES;
859 default:
860 UNREACHABLE(format);
861 }
862
863 return GL_RGBA4_OES;
864 }
865
866 GLenum ConvertDepthStencilFormat(sw::Format format)
867 {
868 switch(format)
869 {
870 case sw::FORMAT_D16:
871 case sw::FORMAT_D24X8:
872 case sw::FORMAT_D32:
873 return GL_DEPTH_COMPONENT16_OES;
874 case sw::FORMAT_D24S8:
875 return GL_DEPTH24_STENCIL8_OES;
876 default:
877 UNREACHABLE(format);
878 }
879
880 return GL_DEPTH24_STENCIL8_OES;
881 }
882}