framework2
996 строк · 22.5 Кб
1#include "ofGLUtils.h"
2#include "ofGLProgrammableRenderer.h"
3#include "ofGraphics.h"
4#include "ofShader.h"
5#include "ofGraphicsBaseTypes.h"
6#include "ofRendererCollection.h"
7#include "ofGLRenderer.h"
8#include "ofPixels.h"
9#include "ofLog.h"
10#include "ofGraphicsConstants.h"
11#include <set>
12
13using std::shared_ptr;
14using std::vector;
15using std::string;
16
17//---------------------------------
18// deprecations
19
20int ofGetGlInternalFormat(const ofPixels& pixels) {
21return ofGetGLInternalFormat(pixels);
22}
23
24int ofGetGlInternalFormat(const ofShortPixels& pixels) {
25return ofGetGLInternalFormat(pixels);
26}
27
28int ofGetGlInternalFormat(const ofFloatPixels& pixels) {
29return ofGetGLInternalFormat(pixels);
30}
31
32std::string ofGetGlInternalFormatName(int glInternalFormat) {
33return ofGetGLInternalFormatName(glInternalFormat);
34}
35
36int ofGetGlTypeFromInternal(int glInternalFormat) {
37return ofGetGLTypeFromInternal(glInternalFormat);
38}
39
40int ofGetGlType(const ofPixels & pixels) {
41return ofGetGLType(pixels);
42}
43
44int ofGetGlType(const ofShortPixels & pixels) {
45return ofGetGLType(pixels);
46}
47
48int ofGetGlType(const ofFloatPixels & pixels) {
49return ofGetGLType(pixels);
50}
51
52//---------------------------------
53int ofGetGLInternalFormat(const ofPixels& pixels) {
54return ofGetGLInternalFormatFromPixelFormat(pixels.getPixelFormat());
55}
56
57//---------------------------------
58int ofGetGLInternalFormat(const ofShortPixels& pixels) {
59#ifndef TARGET_OPENGLES
60switch(pixels.getNumChannels()) {
61case 3: return GL_RGB16;
62case 4: return GL_RGBA16;
63case 2:
64if(ofIsGLProgrammableRenderer()){
65return GL_RG16;
66}else{
67return GL_LUMINANCE16_ALPHA16;
68}
69default:
70if(ofIsGLProgrammableRenderer()){
71return GL_R16;
72}else{
73return GL_LUMINANCE16;
74}
75}
76#else
77ofLogWarning("ofGLUtils") << "ofGetGLInternalFormat(): 16bit textures are not supported in OpenGL ES";
78switch(pixels.getNumChannels()) {
79case 3: return GL_RGB;
80case 4: return GL_RGBA;
81case 2:
82return GL_LUMINANCE_ALPHA;
83default:
84return GL_LUMINANCE;
85}
86#endif
87}
88
89//---------------------------------
90int ofGetGLInternalFormat(const ofFloatPixels& pixels) {
91#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
92switch(pixels.getNumChannels()) {
93case 3: return GL_RGB32F;
94case 4: return GL_RGBA32F;
95case 2:
96if(ofIsGLProgrammableRenderer()){
97return GL_RG32F;
98}else{
99return GL_LUMINANCE_ALPHA32F_ARB;
100}
101default:
102if(ofIsGLProgrammableRenderer()){
103return GL_R32F;
104}else{
105return GL_LUMINANCE32F_ARB;
106}
107}
108#else
109ofLogWarning("ofGLUtils") << "ofGetGLInternalFormat(): float textures not supported in OpenGL ES";
110switch(pixels.getNumChannels()) {
111case 3: return GL_RGB;
112case 4: return GL_RGBA;
113case 2:
114return GL_LUMINANCE_ALPHA;
115default:
116return GL_LUMINANCE;
117}
118#endif
119}
120
121//---------------------------------
122// this is helpful for debugging ofTexture
123string ofGetGLInternalFormatName(int glInternalFormat) {
124switch(glInternalFormat) {
125case GL_RGBA: return "GL_RGBA";
126#ifndef TARGET_OPENGLES
127case GL_RGBA8: return "GL_RGBA8";
128#endif
129case GL_RGB: return "GL_RGB";
130#ifndef TARGET_OPENGLES
131case GL_RGB8: return "GL_RGB8";
132#endif
133case GL_LUMINANCE: return "GL_LUMINANCE";
134#ifndef TARGET_OPENGLES
135case GL_LUMINANCE8: return "GL_LUMINANCE8";
136case GL_RGBA16: return "GL_RGBA16";
137case GL_RGB16: return "GL_RGB16";
138case GL_LUMINANCE16: return "GL_LUMINANCE16";
139case GL_RGBA32F_ARB: return "GL_RGBA32F_ARB";
140case GL_RGB32F_ARB: return "GL_RGB32F_ARB";
141case GL_LUMINANCE32F_ARB: return "GL_LUMINANCE32F_ARB";
142#endif
143case GL_LUMINANCE_ALPHA: return "GL_LUMINANCE_ALPHA";
144#ifndef TARGET_OPENGLES
145case GL_LUMINANCE8_ALPHA8: return "GL_LUMINANCE8_ALPHA8";
146#endif
147default: return "unknown glInternalFormat";
148}
149}
150
151int ofGetGLFormatFromInternal(int glInternalFormat){
152switch(glInternalFormat) {
153case GL_RGBA:
154#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
155case GL_RGBA8:
156case GL_RGBA16:
157case GL_RGBA16F:
158case GL_RGBA16I:
159case GL_RGBA16UI:
160case GL_RGBA32F:
161case GL_RGBA32I:
162case GL_RGBA32UI:
163#endif
164return GL_RGBA;
165#ifdef TARGET_OF_IOS
166case GL_BGRA:
167return GL_BGRA;
168#endif
169
170
171case GL_RGB:
172#ifndef TARGET_OPENGLES
173case GL_RGB8:
174case GL_RGB16:
175case GL_RGB16F:
176case GL_RGB16I:
177case GL_RGB16UI:
178case GL_RGB32F:
179case GL_RGB32I:
180case GL_RGB32UI:
181#endif
182return GL_RGB;
183
184
185case GL_LUMINANCE:
186#ifndef TARGET_OPENGLES
187case GL_LUMINANCE8:
188case GL_LUMINANCE16:
189case GL_LUMINANCE32F_ARB:
190#endif
191return GL_LUMINANCE;
192
193case GL_LUMINANCE_ALPHA:
194#ifndef TARGET_OPENGLES
195case GL_LUMINANCE8_ALPHA8:
196case GL_LUMINANCE16_ALPHA16:
197case GL_LUMINANCE_ALPHA32F_ARB:
198#endif
199return GL_LUMINANCE_ALPHA;
200
201
202case GL_DEPTH_STENCIL:
203return GL_DEPTH_STENCIL;
204
205case GL_DEPTH_COMPONENT:
206#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
207case GL_DEPTH_COMPONENT16:
208case GL_DEPTH_COMPONENT24:
209case GL_DEPTH_COMPONENT32:
210#endif
211return GL_DEPTH_COMPONENT;
212
213case GL_STENCIL_INDEX:
214return GL_STENCIL_INDEX;
215
216#ifndef TARGET_OPENGLES
217case GL_R8:
218case GL_R16:
219case GL_R16I:
220case GL_R16UI:
221case GL_R16F:
222case GL_R32F:
223case GL_R32I:
224case GL_R32UI:
225return GL_RED;
226
227case GL_RG8:
228case GL_RG16:
229case GL_RG16I:
230case GL_RG16UI:
231case GL_RG16F:
232case GL_RG32F:
233case GL_RG32I:
234case GL_RG32UI:
235return GL_RG;
236#endif
237
238#ifndef TARGET_OPENGLES
239case GL_ALPHA8:
240#endif
241case GL_ALPHA:
242return GL_ALPHA;
243
244default:
245ofLogError("ofGLUtils") << "ofGetGLFormatFromInternal(): unknown internal format " << glInternalFormat << ", returning GL_RGBA";
246return GL_RGBA;
247
248}
249}
250
251int ofGetGLTypeFromInternal(int glInternalFormat){
252
253switch(glInternalFormat) {
254case GL_RGB:
255case GL_RGBA:
256case GL_LUMINANCE:
257case GL_LUMINANCE_ALPHA:
258case GL_ALPHA:
259#ifndef TARGET_OPENGLES
260case GL_LUMINANCE8:
261case GL_LUMINANCE8_ALPHA8:
262case GL_R8:
263case GL_RG8:
264case GL_RGB8:
265case GL_RGBA8:
266case GL_ALPHA8:
267#endif
268return GL_UNSIGNED_BYTE;
269
270
271#if !defined(TARGET_OPENGLES) && defined(GL_RGB565)
272case GL_RGB565:
273return GL_UNSIGNED_SHORT_5_6_5;
274break;
275#endif
276
277#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
278case GL_LUMINANCE32F_ARB:
279case GL_LUMINANCE_ALPHA32F_ARB:
280case GL_R32F:
281case GL_RG32F:
282case GL_RGB32F:
283case GL_RGBA32F:
284return GL_FLOAT;
285
286case GL_R16F:
287case GL_RG16F:
288case GL_RGB16F:
289case GL_RGBA16F:
290case GL_LUMINANCE16:
291case GL_LUMINANCE16_ALPHA16:
292case GL_R16:
293case GL_RG16:
294case GL_RGB16:
295case GL_RGBA16:
296return GL_HALF_FLOAT;
297#endif
298
299case GL_DEPTH_STENCIL:
300return GL_UNSIGNED_INT_24_8;
301
302case GL_DEPTH_COMPONENT:
303#ifndef TARGET_OPENGLES
304case GL_DEPTH_COMPONENT16:
305case GL_R16UI:
306case GL_RG16UI:
307case GL_RGB16UI:
308case GL_RGBA16UI:
309#endif
310return GL_UNSIGNED_SHORT;
311
312#ifndef TARGET_OPENGLES
313case GL_R16I:
314case GL_RG16I:
315case GL_RGB16I:
316case GL_RGBA16I:
317return GL_SHORT;
318#endif
319
320#ifndef TARGET_OPENGLES
321case GL_DEPTH_COMPONENT24:
322case GL_DEPTH_COMPONENT32:
323case GL_R32UI:
324case GL_RG32UI:
325case GL_RGB32UI:
326case GL_RGBA32UI:
327return GL_UNSIGNED_INT;
328#endif
329
330#ifndef TARGET_OPENGLES
331case GL_R32I:
332case GL_RG32I:
333case GL_RGB32I:
334case GL_RGBA32I:
335return GL_INT;
336#endif
337
338case GL_STENCIL_INDEX:
339return GL_UNSIGNED_BYTE;
340
341default:
342ofLogError("ofGLUtils") << "ofGetGLTypeFromInternal(): unknown internal format " << glInternalFormat << ", returning GL_UNSIGNED_BYTE";
343return GL_UNSIGNED_BYTE;
344
345}
346}
347
348//---------------------------------
349int ofGetGLType(const ofPixels & pixels) {
350#ifndef TARGET_OPENGLES
351if(pixels.getPixelFormat() == OF_PIXELS_RGB565){
352return GL_UNSIGNED_SHORT_5_6_5;
353}else{
354#endif
355return GL_UNSIGNED_BYTE;
356#ifndef TARGET_OPENGLES
357}
358#endif
359}
360
361//---------------------------------
362int ofGetGLType(const ofShortPixels & pixels) {
363return GL_UNSIGNED_SHORT;
364}
365
366//---------------------------------
367int ofGetGLType(const ofFloatPixels & pixels) {
368return GL_FLOAT;
369}
370
371//---------------------------------
372ofImageType ofGetImageTypeFromGLType(int glType){
373switch(glType){
374case GL_LUMINANCE:
375#ifndef TARGET_OPENGLES
376case GL_LUMINANCE8:
377case GL_LUMINANCE16:
378case GL_LUMINANCE32F_ARB:
379case GL_R8:
380case GL_R16:
381case GL_R16F:
382case GL_R16I:
383case GL_R16UI:
384case GL_R32F:
385case GL_R32I:
386case GL_R32UI:
387case GL_DEPTH_COMPONENT32F:
388case GL_DEPTH_COMPONENT32:
389case GL_DEPTH_COMPONENT16:
390case GL_DEPTH_COMPONENT24:
391case GL_DEPTH_COMPONENT:
392#endif
393return OF_IMAGE_GRAYSCALE;
394
395
396case GL_RGB:
397#ifndef TARGET_OPENGLES
398case GL_RGB8:
399case GL_RGB16:
400case GL_RGB16F:
401case GL_RGB16I:
402case GL_RGB16UI:
403case GL_RGB32F:
404case GL_RGB32I:
405case GL_RGB32UI:
406#endif
407return OF_IMAGE_COLOR;
408
409
410case GL_RGBA:
411#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
412case GL_RGBA8:
413case GL_RGBA16:
414case GL_RGBA16F:
415case GL_RGBA16I:
416case GL_RGBA16UI:
417case GL_RGBA32F:
418case GL_RGBA32I:
419case GL_RGBA32UI:
420#endif
421return OF_IMAGE_COLOR_ALPHA;
422}
423return OF_IMAGE_UNDEFINED;
424}
425
426GLuint ofGetGLPolyMode(ofPolyRenderMode mode){
427#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
428switch(mode){
429case(OF_MESH_POINTS):
430return GL_POINT;
431break;
432case(OF_MESH_WIREFRAME):
433return GL_LINE;
434break;
435case(OF_MESH_FILL):
436return GL_FILL;
437break;
438default:
439ofLogError("ofGLUtils") << "ofGetGLPolyMode(): unknown OF poly mode " << ofToString(mode) << ", returning GL_FILL";
440return GL_FILL;
441break;
442}
443#else
444return 0;
445#endif
446}
447
448ofPolyRenderMode ofGetOFPolyMode(GLuint mode){
449#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
450switch(mode){
451case(GL_POINT):
452return OF_MESH_POINTS;
453break;
454case(GL_LINE):
455return OF_MESH_WIREFRAME;
456break;
457case(GL_FILL):
458return OF_MESH_FILL;
459break;
460default:
461ofLogError("ofGLUtils") << "ofGetOFPolyMode(): unknown GL poly mode " << ofToString(mode) << ", returning OF_MESH_FILL";
462return OF_MESH_FILL;
463break;
464}
465#else
466return OF_MESH_FILL;
467#endif
468}
469
470
471GLuint ofGetGLPrimitiveMode(ofPrimitiveMode mode){
472switch(mode){
473case OF_PRIMITIVE_TRIANGLES:
474return GL_TRIANGLES;
475break;
476case OF_PRIMITIVE_TRIANGLE_STRIP:
477return GL_TRIANGLE_STRIP;
478break;
479case OF_PRIMITIVE_TRIANGLE_FAN:
480return GL_TRIANGLE_FAN;
481break;
482case OF_PRIMITIVE_LINES:
483return GL_LINES;
484break;
485case OF_PRIMITIVE_LINE_STRIP:
486return GL_LINE_STRIP;
487break;
488case OF_PRIMITIVE_LINE_LOOP:
489return GL_LINE_LOOP;
490break;
491case OF_PRIMITIVE_POINTS:
492return GL_POINTS;
493break;
494#ifndef TARGET_OPENGLES
495case OF_PRIMITIVE_LINES_ADJACENCY:
496return GL_LINES_ADJACENCY;
497break;
498case OF_PRIMITIVE_LINE_STRIP_ADJACENCY:
499return GL_LINE_STRIP_ADJACENCY;
500break;
501case OF_PRIMITIVE_TRIANGLES_ADJACENCY:
502return GL_TRIANGLES_ADJACENCY;
503break;
504case OF_PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:
505return GL_TRIANGLE_STRIP_ADJACENCY;
506break;
507case OF_PRIMITIVE_PATCHES:
508return GL_PATCHES;
509break;
510#endif
511default:
512ofLogError("ofGLUtils") << "ofGetGLPrimitiveMode(): unknown OF primitive mode " << ofToString(mode) << ", returning GL_TRIANGLES";
513return GL_TRIANGLES;
514break;
515}
516}
517
518ofPrimitiveMode ofGetOFPrimitiveMode(GLuint mode){
519switch(mode){
520case GL_TRIANGLES:
521return OF_PRIMITIVE_TRIANGLES;
522break;
523case GL_TRIANGLE_STRIP:
524return OF_PRIMITIVE_TRIANGLE_STRIP;
525break;
526case GL_TRIANGLE_FAN:
527return OF_PRIMITIVE_TRIANGLE_FAN;
528break;
529case GL_LINES:
530return OF_PRIMITIVE_LINES;
531break;
532case GL_LINE_STRIP:
533return OF_PRIMITIVE_LINE_STRIP;
534break;
535case GL_LINE_LOOP:
536return OF_PRIMITIVE_LINE_LOOP;
537break;
538case GL_POINTS:
539return OF_PRIMITIVE_POINTS;
540break;
541#ifndef TARGET_OPENGLES
542case GL_LINES_ADJACENCY:
543return OF_PRIMITIVE_LINES_ADJACENCY;
544break;
545case GL_LINE_STRIP_ADJACENCY:
546return OF_PRIMITIVE_LINE_STRIP_ADJACENCY;
547break;
548case GL_TRIANGLES_ADJACENCY:
549return OF_PRIMITIVE_TRIANGLES_ADJACENCY;
550break;
551case GL_TRIANGLE_STRIP_ADJACENCY:
552return OF_PRIMITIVE_TRIANGLE_STRIP_ADJACENCY;
553break;
554case GL_PATCHES:
555return OF_PRIMITIVE_PATCHES;
556break;
557#endif
558default:
559ofLogError("ofGLUtils") << "ofGetOFPrimitiveMode(): unknown GL primitive mode " << ofToString(mode) << ", returning OF_PRIMITIVE_TRIANGLES";
560return OF_PRIMITIVE_TRIANGLES;
561break;
562}
563}
564
565
566int ofGetGLInternalFormatFromPixelFormat(ofPixelFormat pixelFormat){
567switch(pixelFormat){
568case OF_PIXELS_BGRA:
569case OF_PIXELS_RGBA:
570#ifndef TARGET_OPENGLES
571return GL_RGBA8;
572#else
573return GL_RGBA;
574#endif
575case OF_PIXELS_RGB:
576case OF_PIXELS_BGR:
577#ifndef TARGET_OPENGLES
578return GL_RGB8;
579#else
580return GL_RGB;
581#endif
582case OF_PIXELS_RGB565:
583#if defined(TARGET_ANDROID) || defined(TARGET_RASPBERRY_PI_LEGACY)
584return GL_RGB565_OES;
585#elif defined(GL_RGB565)
586return GL_RGB565;
587#else
588return GL_RGB;
589#endif
590case OF_PIXELS_GRAY:
591case OF_PIXELS_NV12:
592case OF_PIXELS_NV21:
593case OF_PIXELS_YV12:
594case OF_PIXELS_I420:
595case OF_PIXELS_Y:
596case OF_PIXELS_U:
597case OF_PIXELS_V:
598#ifndef TARGET_OPENGLES
599if(ofIsGLProgrammableRenderer()){
600return GL_R8;
601}else{
602#endif
603return GL_LUMINANCE;
604#ifndef TARGET_OPENGLES
605}
606#endif
607case OF_PIXELS_GRAY_ALPHA:
608case OF_PIXELS_YUY2:
609case OF_PIXELS_UV:
610case OF_PIXELS_VU:
611#ifndef TARGET_OPENGLES
612if(ofIsGLProgrammableRenderer()){
613return GL_RG8;
614}else{
615#endif
616return GL_LUMINANCE_ALPHA;
617#ifndef TARGET_OPENGLES
618}
619#endif
620default:
621ofLogError("ofGLUtils") << "ofGetGLInternalFormatFromPixelFormat(): unknown OF pixel format "
622<< ofToString(pixelFormat) << ", returning GL_RGBA";
623return GL_RGBA;
624}
625}
626
627int ofGetGLFormatFromPixelFormat(ofPixelFormat pixelFormat){
628switch(pixelFormat){
629case OF_PIXELS_BGRA:
630#ifdef TARGET_OPENGLES
631return GL_BGRA_EXT;
632#else
633return GL_BGRA;
634#endif
635case OF_PIXELS_RGB:
636return GL_RGB;
637case OF_PIXELS_BGR:
638#ifdef TARGET_OPENGLES
639return GL_RGB;
640#else
641return GL_BGR;
642#endif
643case OF_PIXELS_RGBA:
644return GL_RGBA;
645case OF_PIXELS_RGB565:
646return GL_RGB;
647case OF_PIXELS_GRAY:
648case OF_PIXELS_NV12:
649case OF_PIXELS_NV21:
650case OF_PIXELS_YV12:
651case OF_PIXELS_I420:
652case OF_PIXELS_Y:
653case OF_PIXELS_U:
654case OF_PIXELS_V:
655#ifndef TARGET_OPENGLES
656if(ofIsGLProgrammableRenderer()){
657return GL_RED;
658}else{
659#endif
660return GL_LUMINANCE;
661#ifndef TARGET_OPENGLES
662}
663#endif
664case OF_PIXELS_GRAY_ALPHA:
665case OF_PIXELS_YUY2:
666case OF_PIXELS_UV:
667case OF_PIXELS_VU:
668#ifndef TARGET_OPENGLES
669if(ofIsGLProgrammableRenderer()){
670return GL_RG;
671}else{
672#endif
673return GL_LUMINANCE_ALPHA;
674#ifndef TARGET_OPENGLES
675}
676#endif
677default:
678#ifndef TARGET_OPENGLES
679if(ofIsGLProgrammableRenderer()){
680ofLogError("ofGLUtils") << "ofGetGLFormatFromPixelFormat(): unknown OF pixel format "
681<< ofToString(pixelFormat) << ", returning GL_RED";
682return GL_RED;
683}else{
684#endif
685ofLogError("ofGLUtils") << "ofGetGLFormatFromPixelFormat(): unknown OF pixel format "
686<< ofToString(pixelFormat) << ", returning GL_LUMINANCE";
687return GL_LUMINANCE;
688#ifndef TARGET_OPENGLES
689}
690#endif
691}
692}
693
694
695int ofGetNumChannelsFromGLFormat(int glFormat){
696switch(glFormat){
697case GL_RGB:
698return 3;
699#ifdef TARGET_OF_IOS
700case GL_BGRA:
701#endif
702case GL_RGBA:
703return 4;
704case GL_LUMINANCE:
705return 1;
706case GL_LUMINANCE_ALPHA:
707return 2;
708#ifndef TARGET_OPENGLES
709case GL_RED:
710return 1;
711case GL_RG:
712return 2;
713#endif
714default:
715return 1;
716}
717}
718
719int ofGetBytesPerChannelFromGLType(int glType){
720switch(glType) {
721case GL_UNSIGNED_BYTE:
722return 1;
723case GL_UNSIGNED_SHORT:
724return 2;
725
726#if !defined(TARGET_OPENGLES) && defined(GL_RGB565)
727case GL_UNSIGNED_SHORT_5_6_5:
728return 2;
729#endif
730
731#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
732case GL_FLOAT:
733return 4;
734#endif
735case GL_UNSIGNED_INT_24_8:
736return 4;
737
738
739#ifndef TARGET_OPENGLES
740case GL_UNSIGNED_INT:
741return 4;
742#endif
743case GL_HALF_FLOAT:
744return 2;
745
746default:
747ofLogError("ofGetBytesPerChannelFromGLType") << "unknown type returning 1";
748return 1;
749
750}
751}
752
753// Rounds an integer value up to the next multiple of 2,4 and 8.
754#define OF_ROUND_UP_2(num) (((num)+1)&~1)
755#define OF_ROUND_UP_4(num) (((num)+3)&~3)
756#define OF_ROUND_UP_8(num) (((num)+7)&~7)
757
758void ofSetPixelStoreiAlignment(GLenum pname, int w, int bpc, int numChannels){
759int stride = w * numChannels * bpc;
760ofSetPixelStoreiAlignment(pname,stride);
761}
762
763void ofSetPixelStoreiAlignment(GLenum pname, int stride){
764if (OF_ROUND_UP_8 (stride) == stride) {
765glPixelStorei (pname, 8);
766} else if (OF_ROUND_UP_4 (stride) == stride) {
767glPixelStorei (pname, 4);
768} else if (OF_ROUND_UP_2 (stride) == stride) {
769glPixelStorei (pname, 2);
770} else {
771glPixelStorei (pname, 1);
772}
773}
774
775vector<string> ofGLSupportedExtensions(){
776#ifdef TARGET_OPENGLES
777char* extensions = (char*)glGetString(GL_EXTENSIONS);
778if(extensions){
779string extensions_str = extensions;
780return ofSplitString(extensions_str," ");
781}else{
782return vector<string>();
783}
784#else
785int numExtensions=0;
786glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
787std::vector<std::string> extensions;
788for(int i=0;i<numExtensions;i++){
789char* extension = (char*)glGetStringi(GL_EXTENSIONS, i);
790if(extension){
791extensions.emplace_back(extension);
792}
793}
794return extensions;
795#endif
796}
797
798bool ofGLCheckExtension(string searchName){
799#if defined( TARGET_OPENGLES )
800vector<string> extensionsList = ofGLSupportedExtensions();
801std::set<string> extensionsSet;
802extensionsSet.insert(extensionsList.begin(),extensionsList.end());
803return extensionsSet.find(searchName)!=extensionsSet.end();
804#else
805return glewIsSupported(searchName.c_str());
806#endif
807}
808
809bool ofGLSupportsNPOTTextures(){
810#ifndef TARGET_OPENGLES
811return GL_ARB_texture_rectangle;
812#elif !defined(TARGET_EMSCRIPTEN)
813static bool npotChecked = false;
814static bool npotSupported = false;
815if(!npotChecked){
816vector<string> extensionsList = ofGLSupportedExtensions();
817std::set<string> extensionsSet;
818extensionsSet.insert(extensionsList.begin(),extensionsList.end());
819
820npotSupported = extensionsSet.find("GL_OES_texture_npot")!=extensionsSet.end() ||
821extensionsSet.find("APPLE_texture_2D_limited_npot")!=extensionsSet.end() ||
822extensionsSet.find("GL_NV_texture_npot_2D_mipmap")!=extensionsSet.end() ||
823extensionsSet.find("GL_IMG_texture_npot")!=extensionsSet.end() ||
824extensionsSet.find("GL_ARB_texture_non_power_of_two")!=extensionsSet.end();
825npotChecked = true;
826}
827
828return npotSupported;
829#else
830return true;
831#endif
832}
833
834string ofGLSLVersionFromGL(int major, int minor){
835#ifdef TARGET_OPENGLES
836#ifdef TARGET_EMSCRIPTEN
837if( major >= 2 ) { // for emscripten major version refers to WEBGL version
838return "300 es";
839} else {
840return "ES1";
841}
842#else
843return "ES1";
844#endif
845#else
846switch(major){
847case 3:
848if(minor==0){
849return "130";
850}else if(minor==1){
851return "140";
852}else if(minor==2){
853return "150";
854}else{
855return ofToString(major*100+minor*10);
856}
857case 4:
858return ofToString(major*100+minor*10);
859default:
860return "120";
861}
862#endif
863}
864
865string ofGLSLVersionFromGL(){
866int major = 0;
867int minor = 0;
868
869auto glRenderer = std::dynamic_pointer_cast<ofBaseGLRenderer>(ofGetCurrentRenderer());
870if( glRenderer ){
871major = glRenderer->getGLVersionMajor();
872minor = glRenderer->getGLVersionMinor();
873}
874return ofGLSLVersionFromGL(major, minor);
875}
876
877//TODO: unify this with similar in ofGLProgrammableRenderer and ofMaterial
878string ofGLSLGetDefaultHeader(){
879string header = "";
880
881auto glRenderer = std::dynamic_pointer_cast<ofBaseGLRenderer>(ofGetCurrentRenderer());
882
883if( glRenderer ){
884string versionStr = ofGLSLVersionFromGL(glRenderer->getGLVersionMajor(), glRenderer->getGLVersionMinor());
885header = "#version "+versionStr+"\n";
886
887#ifdef TARGET_OPENGLES
888if( versionStr != "ES1" ){
889header += "#extension GL_OES_standard_derivatives : enable\n";
890}
891#ifdef TARGET_ANDROID
892header += "#extension GL_OES_EGL_image_external : require\n";
893#endif
894header += "precision mediump float;\n";
895header += "precision mediump int;\n";
896header += "#define TARGET_OPENGLES\n";
897#else
898if( ofGetUsingArbTex() ){
899if( glRenderer->getGLVersionMajor() < 4 && glRenderer->getGLVersionMinor() < 2 ){
900header += "\n#extension GL_ARB_texture_rectangle : enable";
901}
902}
903#endif
904}
905return header;
906}
907
908#ifndef TARGET_PROGRAMMABLE_GL
909shared_ptr<ofBaseGLRenderer> ofGetGLRenderer(){
910if(ofGetCurrentRenderer()->getType()==ofGLRenderer::TYPE || ofGetCurrentRenderer()->getType()==ofGLProgrammableRenderer::TYPE){
911return (shared_ptr<ofBaseGLRenderer>&)ofGetCurrentRenderer();
912}else if(ofGetCurrentRenderer()->getType()==ofRendererCollection::TYPE){
913return ((shared_ptr<ofRendererCollection>&)ofGetCurrentRenderer())->getGLRenderer();
914}else{
915return shared_ptr<ofGLRenderer>();
916}
917}
918#else
919shared_ptr<ofBaseGLRenderer> ofGetGLRenderer(){
920if(ofGetCurrentRenderer()->getType()==ofGLProgrammableRenderer::TYPE){
921return (shared_ptr<ofBaseGLRenderer>&)ofGetCurrentRenderer();
922}else if(ofGetCurrentRenderer()->getType()==ofRendererCollection::TYPE){
923return ((shared_ptr<ofRendererCollection>&)ofGetCurrentRenderer())->getGLRenderer();
924}else{
925return shared_ptr<ofGLProgrammableRenderer>();
926}
927}
928#endif
929
930#ifndef TARGET_OPENGLES
931namespace{
932void gl_debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, void * user){
933std::ostringstream oss;
934oss << "GL Debug: ";
935
936ofLogLevel level;
937switch (type) {
938case GL_DEBUG_TYPE_ERROR:
939level = OF_LOG_ERROR;
940oss << "ERROR";
941break;
942case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
943level = OF_LOG_WARNING;
944oss << "DEPRECATED_BEHAVIOR";
945break;
946case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
947level = OF_LOG_WARNING;
948oss << "UNDEFINED_BEHAVIOR";
949break;
950case GL_DEBUG_TYPE_PORTABILITY:
951level = OF_LOG_NOTICE;
952oss << "PORTABILITY";
953break;
954case GL_DEBUG_TYPE_PERFORMANCE:
955level = OF_LOG_NOTICE;
956oss << "PERFORMANCE";
957break;
958case GL_DEBUG_TYPE_OTHER:
959default:
960level = OF_LOG_VERBOSE;
961oss << "OTHER";
962break;
963}
964
965switch (severity) {
966case GL_DEBUG_SEVERITY_LOW:
967oss << " (LOW)";
968break;
969case GL_DEBUG_SEVERITY_MEDIUM:
970oss << " (MEDIUM)";
971break;
972case GL_DEBUG_SEVERITY_HIGH:
973oss << " (HIGH)";
974break;
975}
976
977oss << ", " << id << ": " << message;
978
979ofLog(level, oss.str());
980}
981}
982
983void ofEnableGLDebugLog(){
984if(ofGLCheckExtension("GL_KHR_debug") && ofGLCheckExtension("GL_ARB_debug_output")){
985glEnable(GL_DEBUG_OUTPUT);
986glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
987glDebugMessageCallback((GLDEBUGPROC)gl_debug_callback, nullptr);
988}
989}
990
991void ofDisableGLDebugLog(){
992if(ofGLCheckExtension("GL_KHR_debug") && ofGLCheckExtension("GL_ARB_debug_output")){
993glDisable(GL_DEBUG_OUTPUT);
994}
995}
996#endif
997