1 // license:BSD-3-Clause
2 // copyright-holders:Olivier Galibert, R. Belmont
3 //============================================================
4 //
5 //  drawogl.c - SDL software and OpenGL implementation
6 //
7 //  SDLMAME by Olivier Galibert and R. Belmont
8 //
9 //  Note: D3D9 goes to a lot of trouble to fiddle with MODULATE
10 //        mode on textures.  That is the default in OpenGL so we
11 //        don't have to touch it.
12 //
13 //============================================================
14 
15 // standard C headers
16 #include <cmath>
17 #include <cstdio>
18 
19 // MAME headers
20 #include "osdcomm.h"
21 #include "emu.h"
22 #include "emuopts.h"
23 
24 #ifdef OSD_MAC
25 #define GL_SILENCE_DEPRECATION (1)
26 #endif
27 
28 #if !defined(OSD_WINDOWS) && !defined(OSD_MAC)
29 // standard SDL headers
30 #define TOBEMIGRATED 1
31 #include <SDL2/SDL.h>
32 #endif
33 
34 #include "modules/lib/osdlib.h"
35 #include "modules/lib/osdobj_common.h"
36 
37 // OpenGL headers
38 #include "modules/opengl/osd_opengl.h"
39 
40 #include "modules/opengl/gl_shader_tool.h"
41 #include "modules/opengl/gl_shader_mgr.h"
42 
43 #if defined(SDLMAME_MACOSX) || defined(OSD_MAC)
44 #include <cstring>
45 #include <cstdio>
46 #include <sys/types.h>
47 #include <sys/sysctl.h>
48 
49 #ifndef APIENTRY
50 #define APIENTRY
51 #endif
52 #ifndef APIENTRYP
53 #define APIENTRYP APIENTRY *
54 #endif
55 
56 typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
57 typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum, GLuint);
58 typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum, GLsizeiptr, const GLvoid *, GLenum);
59 typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum, GLintptr, GLsizeiptr, const GLvoid *);
60 typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum, GLenum);
61 typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum);
62 typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei, const GLuint *);
63 typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
64 typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);
65 typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum m_target, GLuint framebuffer);
66 typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers);
67 typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers);
68 typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum m_target);
69 typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum m_target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
70 typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers);
71 typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum m_target, GLuint renderbuffer);
72 typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum m_target, GLenum internalformat, GLsizei width, GLsizei height);
73 typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum m_target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
74 typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);
75 #endif
76 
77 // make sure the extensions compile OK everywhere
78 #ifndef GL_TEXTURE_STORAGE_HINT_APPLE
79 #define GL_TEXTURE_STORAGE_HINT_APPLE     0x85bc
80 #endif
81 
82 #ifndef GL_STORAGE_CACHED_APPLE
83 #define GL_STORAGE_CACHED_APPLE           0x85be
84 #endif
85 
86 #ifndef GL_UNPACK_CLIENT_STORAGE_APPLE
87 #define GL_UNPACK_CLIENT_STORAGE_APPLE    0x85b2
88 #endif
89 
90 #ifndef GL_TEXTURE_RECTANGLE_ARB
91 #define GL_TEXTURE_RECTANGLE_ARB          0x84F5
92 #endif
93 
94 #ifndef GL_PIXEL_UNPACK_BUFFER_ARB
95 #define GL_PIXEL_UNPACK_BUFFER_ARB        0x88EC
96 #endif
97 
98 #ifndef GL_STREAM_DRAW
99 #define GL_STREAM_DRAW                    0x88E0
100 #endif
101 
102 #ifndef GL_WRITE_ONLY
103 #define GL_WRITE_ONLY                     0x88B9
104 #endif
105 
106 #ifndef GL_ARRAY_BUFFER_ARB
107 #define GL_ARRAY_BUFFER_ARB               0x8892
108 #endif
109 
110 #ifndef GL_PIXEL_UNPACK_BUFFER_ARB
111 #define GL_PIXEL_UNPACK_BUFFER_ARB        0x88EC
112 #endif
113 
114 #ifndef GL_FRAMEBUFFER_EXT
115 #define GL_FRAMEBUFFER_EXT              0x8D40
116 #define GL_FRAMEBUFFER_COMPLETE_EXT         0x8CD5
117 #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT    0x8CD6
118 #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT    0x8CD7
119 #define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT  0x8CD8
120 #define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT        0x8CD9
121 #define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT       0x8CDA
122 #define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT   0x8CDB
123 #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT   0x8CDC
124 #define GL_FRAMEBUFFER_UNSUPPORTED_EXT          0x8CDD
125 #define GL_RENDERBUFFER_EXT             0x8D41
126 #define GL_DEPTH_COMPONENT16                0x81A5
127 #define GL_DEPTH_COMPONENT24                0x81A6
128 #define GL_DEPTH_COMPONENT32                0x81A7
129 #endif
130 
131 #include "drawogl.h"
132 
133 //============================================================
134 //  DEBUGGING
135 //============================================================
136 
137 #define DEBUG_MODE_SCORES   0
138 #define USE_WIN32_STYLE_LINES   0   // use the same method baseline does - yields somewhat nicer vectors but a little buggy
139 
140 //============================================================
141 //  CONSTANTS
142 //============================================================
143 
144 enum
145 {
146 	TEXTURE_TYPE_NONE,
147 	TEXTURE_TYPE_PLAIN,
148 	TEXTURE_TYPE_DYNAMIC,
149 	TEXTURE_TYPE_SHADER,
150 	TEXTURE_TYPE_SURFACE
151 };
152 
153 
154 //============================================================
155 //  MACROS
156 //============================================================
157 
158 // texture formats
159 // This used to be an enum, but these are now defines so we can use them as
160 // preprocessor conditionals
161 #define SDL_TEXFORMAT_ARGB32            (0) // non-16-bit textures or specials
162 #define SDL_TEXFORMAT_RGB32             (1)
163 #define SDL_TEXFORMAT_RGB32_PALETTED    (2)
164 #define SDL_TEXFORMAT_YUY16             (3)
165 #define SDL_TEXFORMAT_YUY16_PALETTED    (4)
166 #define SDL_TEXFORMAT_PALETTE16         (5)
167 #define SDL_TEXFORMAT_RGB15             (6)
168 #define SDL_TEXFORMAT_RGB15_PALETTED    (7)
169 #define SDL_TEXFORMAT_PALETTE16A        (8)
170 #if 0
171 // special texture formats for 16bpp texture destination support, do not use
172 // to address the tex properties / tex functions arrays!
173 #define SDL_TEXFORMAT_PALETTE16_ARGB1555    (16)
174 #define SDL_TEXFORMAT_RGB15_ARGB1555        (17)
175 #define SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555   (18)
176 #endif
177 
178 #define FSWAP(var1, var2) do { float temp = var1; var1 = var2; var2 = temp; } while (0)
179 #define GL_NO_PRIMITIVE -1
180 
181 /* line_aa_step is used for drawing antialiased lines */
182 struct line_aa_step
183 {
184 	float       xoffs, yoffs;               // X/Y deltas
185 	float       weight;                 // weight contribution
186 };
187 
188 #if 0
189 static const line_aa_step line_aa_1step[] =
190 {
191 	{  0.00f,  0.00f,  1.00f  },
192 	{ 0 }
193 };
194 
195 static const line_aa_step line_aa_4step[] =
196 {
197 	{ -0.25f,  0.00f,  0.25f  },
198 	{  0.25f,  0.00f,  0.25f  },
199 	{  0.00f, -0.25f,  0.25f  },
200 	{  0.00f,  0.25f,  0.25f  },
201 	{ 0 }
202 };
203 #endif
204 
205 //============================================================
206 //  INLINES
207 //============================================================
208 
texture_compute_hash(const render_texinfo * texture,uint32_t flags)209 HashT renderer_ogl::texture_compute_hash(const render_texinfo *texture, uint32_t flags)
210 {
211 	HashT h = (HashT)texture->base ^ (flags & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK));
212 	//printf("hash %d\n", (int) h % HASH_SIZE);
213 	return (h >> 8) % HASH_SIZE;
214 }
215 
set_blendmode(int blendmode)216 void renderer_ogl::set_blendmode(int blendmode)
217 {
218 	// try to minimize texture state changes
219 	if (blendmode != m_last_blendmode)
220 	{
221 		switch (blendmode)
222 		{
223 			case BLENDMODE_NONE:
224 				glDisable(GL_BLEND);
225 				break;
226 			case BLENDMODE_ALPHA:
227 				glEnable(GL_BLEND);
228 				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
229 				break;
230 			case BLENDMODE_RGB_MULTIPLY:
231 				glEnable(GL_BLEND);
232 				glBlendFunc(GL_DST_COLOR, GL_ZERO);
233 				break;
234 			case BLENDMODE_ADD:
235 				glEnable(GL_BLEND);
236 				glBlendFunc(GL_SRC_ALPHA, GL_ONE);
237 				break;
238 		}
239 
240 		m_last_blendmode = blendmode;
241 	}
242 }
243 
244 //============================================================
245 //  STATIC VARIABLES
246 //============================================================
247 
248 // OGL 1.3
249 #if defined(GL_ARB_multitexture) && !defined(OSD_MAC)
250 static PFNGLACTIVETEXTUREARBPROC pfn_glActiveTexture    = nullptr;
251 #else
252 static PFNGLACTIVETEXTUREPROC pfn_glActiveTexture   = nullptr;
253 #endif
254 
255 // VBO
256 static PFNGLGENBUFFERSPROC pfn_glGenBuffers     = nullptr;
257 static PFNGLDELETEBUFFERSPROC pfn_glDeleteBuffers   = nullptr;
258 static PFNGLBINDBUFFERPROC pfn_glBindBuffer     = nullptr;
259 static PFNGLBUFFERDATAPROC pfn_glBufferData     = nullptr;
260 static PFNGLBUFFERSUBDATAPROC pfn_glBufferSubData   = nullptr;
261 
262 // PBO
263 static PFNGLMAPBUFFERPROC     pfn_glMapBuffer       = nullptr;
264 static PFNGLUNMAPBUFFERPROC   pfn_glUnmapBuffer     = nullptr;
265 
266 // FBO
267 static PFNGLISFRAMEBUFFEREXTPROC   pfn_glIsFramebuffer          = nullptr;
268 static PFNGLBINDFRAMEBUFFEREXTPROC pfn_glBindFramebuffer        = nullptr;
269 static PFNGLDELETEFRAMEBUFFERSEXTPROC pfn_glDeleteFramebuffers      = nullptr;
270 static PFNGLGENFRAMEBUFFERSEXTPROC pfn_glGenFramebuffers        = nullptr;
271 static PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC pfn_glCheckFramebufferStatus  = nullptr;
272 static PFNGLFRAMEBUFFERTEXTURE2DEXTPROC pfn_glFramebufferTexture2D  = nullptr;
273 
274 static int glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN;
275 
276 //============================================================
277 //  Textures
278 //============================================================
279 
280 static void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags);
281 
282 //============================================================
283 //  Static Variables
284 //============================================================
285 
286 bool renderer_ogl::s_shown_video_info = false;
287 bool renderer_ogl::s_dll_loaded = false;
288 
init(running_machine & machine)289 void renderer_ogl::init(running_machine &machine)
290 {
291 	s_dll_loaded = false;
292 
293 	load_gl_lib(machine);
294 #if defined(OSD_WINDOWS)
295 	osd_printf_verbose("Using Windows OpenGL driver\n");
296 #else
297 	osd_printf_verbose("Using SDL multi-window OpenGL driver (SDL 2.0+)\n");
298 #endif
299 }
300 
301 //============================================================
302 // CONSTRUCTOR & DESTRUCTOR
303 //============================================================
304 
~renderer_ogl()305 renderer_ogl::~renderer_ogl()
306 {
307 	// free the memory in the window
308 	destroy_all_textures();
309 
310 	delete m_gl_context;
311 	m_gl_context = nullptr;
312 }
313 
exit()314 void renderer_ogl::exit()
315 {
316 	for (int i = 0; i < video_config.glsl_shader_mamebm_num; i++)
317 	{
318 		if (nullptr != video_config.glsl_shader_mamebm[i])
319 		{
320 			free(video_config.glsl_shader_mamebm[i]);
321 			video_config.glsl_shader_mamebm[i] = nullptr;
322 		}
323 	}
324 	for (int i =0; i < video_config.glsl_shader_scrn_num; i++)
325 	{
326 		if (nullptr != video_config.glsl_shader_scrn[i])
327 		{
328 			free(video_config.glsl_shader_scrn[i]);
329 			video_config.glsl_shader_scrn[i] = nullptr;
330 		}
331 	}
332 }
333 
334 //============================================================
335 // Load the OGL function addresses
336 //============================================================
337 
loadgl_functions(osd_gl_context * context)338 static void loadgl_functions(osd_gl_context *context)
339 {
340 #ifdef USE_DISPATCH_GL
341 
342 	int err_count = 0;
343 
344 	/* the following is tricky ... #func will be expanded to glBegin
345 	 * while func will be expanded to disp_p->glBegin
346 	 */
347 
348 	#define OSD_GL(ret,func,params) \
349 	if (!( func = (ret (APIENTRY *)params) context->getProcAddress( #func ) )) \
350 		{ err_count++; osd_printf_error("GL function %s not found!\n", #func ); }
351 
352 	#define OSD_GL_UNUSED(ret,func,params)
353 
354 	#define GET_GLFUNC 1
355 	#include "modules/opengl/osd_opengl.h"
356 	#undef GET_GLFUNC
357 
358 	if (err_count)
359 		fatalerror("Error loading GL library functions, giving up\n");
360 
361 #endif
362 }
363 
364 //============================================================
365 // Load GL library
366 //============================================================
367 
368 #ifdef USE_DISPATCH_GL
369 osd_gl_dispatch *gl_dispatch = nullptr;
370 #endif
371 
load_gl_lib(running_machine & machine)372 void renderer_ogl::load_gl_lib(running_machine &machine)
373 {
374 	if (!s_dll_loaded)
375 	{
376 #ifndef OSD_WINDOWS
377 #ifdef USE_DISPATCH_GL
378 		/*
379 		 *  directfb and and x11 use this env var
380 		 *   SDL_VIDEO_GL_DRIVER
381 		 */
382 		const char *stemp;
383 
384 		stemp = downcast<sdl_options &>(machine.options()).gl_lib();
385 		if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) == 0)
386 			stemp = nullptr;
387 
388 		if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==nullptr
389 		{
390 			fatalerror("Unable to load opengl library: %s\n", stemp ? stemp : "<default>");
391 		}
392 		osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>");
393 		/* FIXME: must be freed as well */
394 #endif
395 #endif
396 #ifdef USE_DISPATCH_GL
397 		gl_dispatch = new osd_gl_dispatch;
398 #endif
399 		s_dll_loaded = true;
400 	}
401 }
402 
initialize_gl()403 void renderer_ogl::initialize_gl()
404 {
405 	int has_and_allow_texturerect = 0;
406 
407 	char *extstr = (char *)glGetString(GL_EXTENSIONS);
408 	char *vendor = (char *)glGetString(GL_VENDOR);
409 
410 	//printf("%p\n", extstr);
411 #ifdef OSD_WINDOWS
412 	if (!extstr)
413 		extstr = (char *)"";
414 #endif
415 	// print out the driver info for debugging
416 	if (!s_shown_video_info)
417 	{
418 		osd_printf_verbose("OpenGL: %s\nOpenGL: %s\nOpenGL: %s\n", vendor, (char *)glGetString(GL_RENDERER), (char *)glGetString(GL_VERSION));
419 	}
420 
421 	m_usetexturerect = 0;
422 	m_texpoweroftwo = 1;
423 	m_usevbo = 0;
424 	m_usepbo = 0;
425 	m_usefbo = 0;
426 	m_useglsl = 0;
427 
428 	if (video_config.allowtexturerect && (strstr(extstr, "GL_ARB_texture_rectangle") ||  strstr(extstr, "GL_EXT_texture_rectangle")))
429 	{
430 		has_and_allow_texturerect = 1;
431 		if (!s_shown_video_info)
432 		{
433 			osd_printf_verbose("OpenGL: texture rectangle supported\n");
434 		}
435 	}
436 
437 	// does this card support non-power-of-two sized textures?  (they're faster, so use them if possible)
438 	if ( !video_config.forcepow2texture && strstr(extstr, "GL_ARB_texture_non_power_of_two"))
439 	{
440 		if (!s_shown_video_info)
441 		{
442 			osd_printf_verbose("OpenGL: non-power-of-2 textures supported (new method)\n");
443 		}
444 					m_texpoweroftwo = 0;
445 	}
446 	else
447 	{
448 		// second chance: GL_ARB_texture_rectangle or GL_EXT_texture_rectangle (old version)
449 		if (has_and_allow_texturerect)
450 		{
451 			if (!s_shown_video_info)
452 			{
453 				osd_printf_verbose("OpenGL: non-power-of-2 textures supported (old method)\n");
454 			}
455 			m_usetexturerect = 1;
456 		}
457 		else
458 		{
459 			if (!s_shown_video_info)
460 			{
461 				osd_printf_verbose("OpenGL: forcing power-of-2 textures (creation, not copy)\n");
462 			}
463 		}
464 	}
465 
466 	if (strstr(extstr, "GL_ARB_vertex_buffer_object"))
467 	{
468 		m_usevbo = video_config.vbo;
469 		if (!s_shown_video_info)
470 		{
471 			if(m_usevbo)
472 				osd_printf_verbose("OpenGL: vertex buffer supported\n");
473 			else
474 				osd_printf_verbose("OpenGL: vertex buffer supported, but disabled\n");
475 		}
476 	}
477 
478 	if (strstr(extstr, "GL_ARB_pixel_buffer_object"))
479 	{
480 		if( m_usevbo )
481 		{
482 			m_usepbo = video_config.pbo;
483 			if (!s_shown_video_info)
484 			{
485 				if(m_usepbo)
486 					osd_printf_verbose("OpenGL: pixel buffers supported\n");
487 				else
488 					osd_printf_verbose("OpenGL: pixel buffers supported, but disabled\n");
489 			}
490 		}
491 		else
492 		{
493 			if (!s_shown_video_info)
494 			{
495 				osd_printf_verbose("OpenGL: pixel buffers supported, but disabled due to disabled vbo\n");
496 			}
497 		}
498 	}
499 	else
500 	{
501 		if (!s_shown_video_info)
502 		{
503 			osd_printf_verbose("OpenGL: pixel buffers not supported\n");
504 		}
505 	}
506 
507 	if (strstr(extstr, "GL_EXT_framebuffer_object"))
508 	{
509 		m_usefbo = 1;
510 		if (!s_shown_video_info)
511 		{
512 			if(m_usefbo)
513 				osd_printf_verbose("OpenGL: framebuffer object supported\n");
514 			else
515 				osd_printf_verbose("OpenGL: framebuffer object not supported\n");
516 		}
517 	}
518 
519 	if (strstr(extstr, "GL_ARB_shader_objects") &&
520 		strstr(extstr, "GL_ARB_shading_language_100") &&
521 		strstr(extstr, "GL_ARB_vertex_shader") &&
522 		strstr(extstr, "GL_ARB_fragment_shader")
523 		)
524 	{
525 		m_useglsl = video_config.glsl;
526 		if (!s_shown_video_info)
527 		{
528 			if(m_useglsl)
529 				osd_printf_verbose("OpenGL: GLSL supported\n");
530 			else
531 				osd_printf_verbose("OpenGL: GLSL supported, but disabled\n");
532 		}
533 	}
534 	else
535 	{
536 		if (!s_shown_video_info)
537 		{
538 			osd_printf_verbose("OpenGL: GLSL not supported\n");
539 		}
540 	}
541 
542 #ifdef TOBEMIGRATED
543 	if (osd_getenv(SDLENV_VMWARE) != nullptr)
544 	{
545 		m_usetexturerect = 1;
546 		m_texpoweroftwo = 1;
547 	}
548 #endif
549 	glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&m_texture_max_width);
550 	glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&m_texture_max_height);
551 	if (!s_shown_video_info)
552 	{
553 		osd_printf_verbose("OpenGL: max texture size %d x %d\n", m_texture_max_width, m_texture_max_height);
554 	}
555 
556 	s_shown_video_info = true;
557 
558 }
559 //============================================================
560 //  sdl_info::create
561 //============================================================
562 
create()563 int renderer_ogl::create()
564 {
565 	auto win = assert_window();
566 
567 	// create renderer
568 #if defined(OSD_WINDOWS)
569 	m_gl_context = new win_gl_context(std::static_pointer_cast<win_window_info>(win)->platform_window());
570 #elif defined(OSD_MAC)
571 // TODO
572 //  m_gl_context = new mac_gl_context(std::static_pointer_cast<mac_window_info>(win)->platform_window());
573 #else
574 	m_gl_context = new sdl_gl_context(std::static_pointer_cast<sdl_window_info>(win)->platform_window());
575 #endif
576 	if  (m_gl_context->LastErrorMsg() != nullptr)
577 	{
578 		osd_printf_error("%s\n", m_gl_context->LastErrorMsg());
579 		return 1;
580 	}
581 	m_gl_context->SetSwapInterval(video_config.waitvsync ? 1 : 0);
582 
583 
584 	m_blittimer = 0;
585 	m_surf_w = 0;
586 	m_surf_h = 0;
587 
588 	m_initialized = 0;
589 
590 	// in case any textures try to come up before these are validated,
591 	// OpenGL guarantees all implementations can handle something this size.
592 	m_texture_max_width = 64;
593 	m_texture_max_height = 64;
594 
595 	/* load any GL function addresses
596 	 * this must be done here because we need a context
597 	 */
598 	loadgl_functions(m_gl_context);
599 	initialize_gl();
600 
601 
602 	m_init_context = 0;
603 
604 	osd_printf_verbose("Leave renderer_ogl::create\n");
605 	return 0;
606 }
607 
608 
609 //============================================================
610 //  drawsdl_xy_to_render_target
611 //============================================================
612 #ifndef OSD_WINDOWS
xy_to_render_target(int x,int y,int * xt,int * yt)613 int renderer_ogl::xy_to_render_target(int x, int y, int *xt, int *yt)
614 {
615 	*xt = x - m_last_hofs;
616 	*yt = y - m_last_vofs;
617 	if (*xt<0 || *xt >= m_blit_dim.width())
618 		return 0;
619 	if (*yt<0 || *yt >= m_blit_dim.height())
620 		return 0;
621 	return 1;
622 }
623 #endif
624 
625 //============================================================
626 //  renderer_ogl::destroy_all_textures
627 //============================================================
628 
destroy_all_textures()629 void renderer_ogl::destroy_all_textures()
630 {
631 	ogl_texture_info *texture = nullptr;
632 	bool lock=false;
633 	int i;
634 
635 	if ( !m_initialized )
636 		return;
637 
638 	auto win = try_getwindow();
639 
640 	// During destroy this can get called
641 	// and the window is no longer available
642 	if (win == nullptr)
643 		return;
644 
645 	m_gl_context->MakeCurrent();
646 
647 	if(win->m_primlist)
648 	{
649 		lock=true;
650 		win->m_primlist->acquire_lock();
651 	}
652 
653 	glFinish();
654 
655 	texture_all_disable();
656 	glFinish();
657 	glDisableClientState(GL_VERTEX_ARRAY);
658 
659 	i=0;
660 	while (i<HASH_SIZE+OVERFLOW_SIZE)
661 	{
662 		texture = m_texhash[i];
663 		m_texhash[i] = nullptr;
664 		if (texture != nullptr)
665 		{
666 			if(m_usevbo)
667 			{
668 				pfn_glDeleteBuffers( 1, &(texture->texCoordBufferName) );
669 				texture->texCoordBufferName=0;
670 			}
671 
672 			if(m_usepbo && texture->pbo)
673 			{
674 				pfn_glDeleteBuffers( 1, (GLuint *)&(texture->pbo) );
675 				texture->pbo=0;
676 			}
677 
678 			if( m_glsl_program_num > 1 )
679 			{
680 				assert(m_usefbo);
681 				pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]);
682 				glDeleteTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]);
683 			}
684 
685 			if ( m_glsl_program_mb2sc < m_glsl_program_num - 1 )
686 			{
687 				assert(m_usefbo);
688 				pfn_glDeleteFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]);
689 				glDeleteTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]);
690 			}
691 
692 			glDeleteTextures(1, (GLuint *)&texture->texture);
693 			if ( texture->data_own )
694 			{
695 				free(texture->data);
696 				texture->data=nullptr;
697 				texture->data_own=false;
698 			}
699 			delete texture;
700 		}
701 		i++;
702 	}
703 	if ( m_useglsl )
704 	{
705 		glsl_shader_free(m_glsl);
706 		m_glsl = nullptr;
707 	}
708 
709 	m_initialized = 0;
710 
711 	if (lock)
712 		win->m_primlist->release_lock();
713 }
714 //============================================================
715 //  loadGLExtensions
716 //============================================================
717 
loadGLExtensions()718 void renderer_ogl::loadGLExtensions()
719 {
720 	static int _once = 1;
721 
722 	// usevbo=false; // You may want to switch VBO and PBO off, by uncommenting this statement
723 	// usepbo=false; // You may want to switch PBO off, by uncommenting this statement
724 	// useglsl=false; // You may want to switch GLSL off, by uncommenting this statement
725 
726 	if (! m_usevbo)
727 	{
728 		if(m_usepbo) // should never ever happen ;-)
729 		{
730 			if (_once)
731 			{
732 				osd_printf_warning("OpenGL: PBO not supported, no VBO support. (sdlmame error)\n");
733 			}
734 			m_usepbo=false;
735 		}
736 		if(m_useglsl) // should never ever happen ;-)
737 		{
738 			if (_once)
739 			{
740 				osd_printf_warning("OpenGL: GLSL not supported, no VBO support. (sdlmame error)\n");
741 			}
742 			m_useglsl=false;
743 		}
744 	}
745 
746 	// Get Pointers To The GL Functions
747 	// VBO:
748 	if( m_usevbo )
749 	{
750 		pfn_glGenBuffers = (PFNGLGENBUFFERSPROC) m_gl_context->getProcAddress("glGenBuffers");
751 		pfn_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) m_gl_context->getProcAddress("glDeleteBuffers");
752 		pfn_glBindBuffer = (PFNGLBINDBUFFERPROC) m_gl_context->getProcAddress("glBindBuffer");
753 		pfn_glBufferData = (PFNGLBUFFERDATAPROC) m_gl_context->getProcAddress("glBufferData");
754 		pfn_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) m_gl_context->getProcAddress("glBufferSubData");
755 	}
756 	// PBO:
757 	if ( m_usepbo )
758 	{
759 		pfn_glMapBuffer  = (PFNGLMAPBUFFERPROC) m_gl_context->getProcAddress("glMapBuffer");
760 		pfn_glUnmapBuffer= (PFNGLUNMAPBUFFERPROC) m_gl_context->getProcAddress("glUnmapBuffer");
761 	}
762 	// FBO:
763 	if ( m_usefbo )
764 	{
765 		pfn_glIsFramebuffer = (PFNGLISFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glIsFramebufferEXT");
766 		pfn_glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC) m_gl_context->getProcAddress("glBindFramebufferEXT");
767 		pfn_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glDeleteFramebuffersEXT");
768 		pfn_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC) m_gl_context->getProcAddress("glGenFramebuffersEXT");
769 		pfn_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) m_gl_context->getProcAddress("glCheckFramebufferStatusEXT");
770 		pfn_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) m_gl_context->getProcAddress("glFramebufferTexture2DEXT");
771 	}
772 
773 	if ( m_usevbo &&
774 			( !pfn_glGenBuffers || !pfn_glDeleteBuffers ||
775 			!pfn_glBindBuffer || !pfn_glBufferData || !pfn_glBufferSubData
776 		) )
777 	{
778 		m_usepbo=false;
779 		if (_once)
780 		{
781 			osd_printf_warning("OpenGL: VBO not supported, missing: ");
782 			if (!pfn_glGenBuffers)
783 			{
784 				osd_printf_warning("glGenBuffers, ");
785 			}
786 			if (!pfn_glDeleteBuffers)
787 			{
788 				osd_printf_warning("glDeleteBuffers");
789 			}
790 			if (!pfn_glBindBuffer)
791 			{
792 				osd_printf_warning("glBindBuffer, ");
793 			}
794 			if (!pfn_glBufferData)
795 			{
796 				osd_printf_warning("glBufferData, ");
797 			}
798 			if (!pfn_glBufferSubData)
799 			{
800 				osd_printf_warning("glBufferSubData, ");
801 			}
802 			osd_printf_warning("\n");
803 		}
804 		if ( m_usevbo )
805 		{
806 			if (_once)
807 			{
808 				osd_printf_warning("OpenGL: PBO not supported, no VBO support.\n");
809 			}
810 			m_usepbo=false;
811 		}
812 	}
813 
814 	if ( m_usepbo && ( !pfn_glMapBuffer || !pfn_glUnmapBuffer ) )
815 	{
816 		m_usepbo=false;
817 		if (_once)
818 		{
819 			osd_printf_warning("OpenGL: PBO not supported, missing: ");
820 			if (!pfn_glMapBuffer)
821 			{
822 				osd_printf_warning("glMapBuffer, ");
823 			}
824 			if (!pfn_glUnmapBuffer)
825 			{
826 				osd_printf_warning("glUnmapBuffer, ");
827 			}
828 			osd_printf_warning("\n");
829 		}
830 	}
831 
832 	if ( m_usefbo &&
833 		( !pfn_glIsFramebuffer || !pfn_glBindFramebuffer || !pfn_glDeleteFramebuffers ||
834 			!pfn_glGenFramebuffers || !pfn_glCheckFramebufferStatus || !pfn_glFramebufferTexture2D
835 		))
836 	{
837 		m_usefbo=false;
838 		if (_once)
839 		{
840 			osd_printf_warning("OpenGL: FBO not supported, missing: ");
841 			if (!pfn_glIsFramebuffer)
842 			{
843 				osd_printf_warning("pfn_glIsFramebuffer, ");
844 			}
845 			if (!pfn_glBindFramebuffer)
846 			{
847 				osd_printf_warning("pfn_glBindFramebuffer, ");
848 			}
849 			if (!pfn_glDeleteFramebuffers)
850 			{
851 				osd_printf_warning("pfn_glDeleteFramebuffers, ");
852 			}
853 			if (!pfn_glGenFramebuffers)
854 			{
855 				osd_printf_warning("pfn_glGenFramebuffers, ");
856 			}
857 			if (!pfn_glCheckFramebufferStatus)
858 			{
859 				osd_printf_warning("pfn_glCheckFramebufferStatus, ");
860 			}
861 			if (!pfn_glFramebufferTexture2D)
862 			{
863 				osd_printf_warning("pfn_glFramebufferTexture2D, ");
864 			}
865 			osd_printf_warning("\n");
866 		}
867 	}
868 
869 	if (_once)
870 	{
871 		if ( m_usevbo )
872 		{
873 			osd_printf_verbose("OpenGL: VBO supported\n");
874 		}
875 		else
876 		{
877 			osd_printf_warning("OpenGL: VBO not supported\n");
878 		}
879 
880 		if ( m_usepbo )
881 		{
882 			osd_printf_verbose("OpenGL: PBO supported\n");
883 		}
884 		else
885 		{
886 			osd_printf_warning("OpenGL: PBO not supported\n");
887 		}
888 
889 		if ( m_usefbo )
890 		{
891 			osd_printf_verbose("OpenGL: FBO supported\n");
892 		}
893 		else
894 		{
895 			osd_printf_warning("OpenGL: FBO not supported\n");
896 		}
897 	}
898 
899 	if ( m_useglsl )
900 	{
901 		#if defined(GL_ARB_multitexture) && !defined(OSD_MAC)
902 		pfn_glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) m_gl_context->getProcAddress("glActiveTextureARB");
903 		#else
904 		pfn_glActiveTexture = (PFNGLACTIVETEXTUREPROC) m_gl_context->getProcAddress("glActiveTexture");
905 		#endif
906 		if (!pfn_glActiveTexture)
907 		{
908 			if (_once)
909 			{
910 				osd_printf_warning("OpenGL: GLSL disabled, glActiveTexture(ARB) not supported\n");
911 			}
912 			m_useglsl = 0;
913 		}
914 	}
915 
916 	if ( m_useglsl )
917 	{
918 		m_glsl = glsl_shader_init(m_gl_context);
919 		m_useglsl = (m_glsl != nullptr ? 1 : 0);
920 
921 		if ( ! m_useglsl )
922 		{
923 			if (_once)
924 			{
925 				osd_printf_warning("OpenGL: GLSL supported, but shader instantiation failed - disabled\n");
926 			}
927 		}
928 	}
929 
930 	if ( m_useglsl )
931 	{
932 		if (assert_window()->prescale() != 1 )
933 		{
934 			m_useglsl = 0;
935 			if (_once)
936 			{
937 				osd_printf_warning("OpenGL: GLSL supported, but disabled due to: prescale !=1 \n");
938 			}
939 		}
940 	}
941 
942 	if ( m_useglsl )
943 	{
944 		int i;
945 		video_config.filter = false;
946 		glsl_shader_feature = GLSL_SHADER_FEAT_PLAIN;
947 		m_glsl_program_num = 0;
948 		m_glsl_program_mb2sc = 0;
949 
950 		for(i=0; i<video_config.glsl_shader_mamebm_num; i++)
951 		{
952 			if ( !m_usefbo && m_glsl_program_num==1 )
953 			{
954 				if (_once)
955 				{
956 					osd_printf_verbose("OpenGL: GLSL multipass not supported, due to unsupported FBO. Skipping followup shader\n");
957 				}
958 				break;
959 			}
960 
961 			if ( glsl_shader_add_mamebm(m_glsl, video_config.glsl_shader_mamebm[i], m_glsl_program_num) )
962 			{
963 				osd_printf_error("OpenGL: GLSL loading mame bitmap shader %d failed (%s)\n",
964 					i, video_config.glsl_shader_mamebm[i]);
965 			} else {
966 				glsl_shader_feature = GLSL_SHADER_FEAT_CUSTOM;
967 				if (_once)
968 				{
969 					osd_printf_verbose("OpenGL: GLSL using mame bitmap shader filter %d: '%s'\n",
970 						m_glsl_program_num, video_config.glsl_shader_mamebm[i]);
971 				}
972 				m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it.
973 				m_glsl_program_num++;
974 			}
975 		}
976 
977 		if ( video_config.glsl_shader_scrn_num > 0 && m_glsl_program_num==0 )
978 		{
979 			osd_printf_verbose("OpenGL: GLSL cannot use screen bitmap shader without bitmap shader\n");
980 		}
981 
982 		for(i=0; m_usefbo && m_glsl_program_num>0 && i<video_config.glsl_shader_scrn_num; i++)
983 		{
984 			if ( glsl_shader_add_scrn(m_glsl, video_config.glsl_shader_scrn[i],
985 											m_glsl_program_num-1-m_glsl_program_mb2sc) )
986 			{
987 				osd_printf_error("OpenGL: GLSL loading screen bitmap shader %d failed (%s)\n",
988 					i, video_config.glsl_shader_scrn[i]);
989 			} else {
990 				if (_once)
991 				{
992 					osd_printf_verbose("OpenGL: GLSL using screen bitmap shader filter %d: '%s'\n",
993 						m_glsl_program_num, video_config.glsl_shader_scrn[i]);
994 				}
995 				m_glsl_program_num++;
996 			}
997 		}
998 
999 		if ( 0==m_glsl_program_num &&
1000 				0 <= video_config.glsl_filter && video_config.glsl_filter < GLSL_SHADER_FEAT_INT_NUMBER )
1001 		{
1002 			m_glsl_program_mb2sc = m_glsl_program_num; // the last mame_bitmap (mb) shader does it.
1003 			m_glsl_program_num++;
1004 			glsl_shader_feature = video_config.glsl_filter;
1005 
1006 			if (_once)
1007 			{
1008 				osd_printf_verbose("OpenGL: GLSL using shader filter '%s', idx: %d, num %d (vid filter: %d)\n",
1009 					glsl_shader_get_filter_name_mamebm(glsl_shader_feature),
1010 					glsl_shader_feature, m_glsl_program_num, video_config.filter);
1011 			}
1012 		}
1013 
1014 	} else {
1015 		if (_once)
1016 		{
1017 			osd_printf_verbose("OpenGL: using vid filter: %d\n", video_config.filter);
1018 		}
1019 	}
1020 
1021 	_once = 0;
1022 }
1023 
1024 //============================================================
1025 //  sdl_info::draw
1026 //============================================================
1027 
draw(const int update)1028 int renderer_ogl::draw(const int update)
1029 {
1030 	ogl_texture_info *texture=nullptr;
1031 	float vofs, hofs;
1032 	int  pendingPrimitive=GL_NO_PRIMITIVE, curPrimitive=GL_NO_PRIMITIVE;
1033 
1034 #ifdef TOBEMIGRATED
1035 	if (video_config.novideo)
1036 	{
1037 		return 0;
1038 	}
1039 #endif
1040 
1041 	auto win = assert_window();
1042 
1043 	osd_dim wdim = win->get_size();
1044 
1045 	if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height))
1046 	{
1047 		destroy_all_textures();
1048 		m_width = wdim.width();
1049 		m_height = wdim.height();
1050 		m_blittimer = 3;
1051 		m_init_context = 1;
1052 		clear_flags(FI_CHANGED);
1053 	}
1054 
1055 	m_gl_context->MakeCurrent();
1056 
1057 	if (m_init_context)
1058 	{
1059 		// do some one-time OpenGL setup
1060 		// FIXME: SRGB conversion is working on SDL2, may be of use
1061 		// when we eventually target gamma and monitor profiles.
1062 		//glEnable(GL_FRAMEBUFFER_SRGB);
1063 		glShadeModel(GL_SMOOTH);
1064 		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1065 		glClearDepth(1.0f);
1066 		glEnable(GL_DEPTH_TEST);
1067 		glDepthFunc(GL_LEQUAL);
1068 		glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1069 	}
1070 
1071 	// only clear if the geometry changes (and for 2 frames afterward to clear double and triple buffers)
1072 	if ((m_blittimer > 0) || has_flags(FLAG_HAS_VECTOR_SCREEN))
1073 	{
1074 		glClear(GL_COLOR_BUFFER_BIT);
1075 		m_blittimer--;
1076 	}
1077 
1078 	// FIXME: remove m_surf_w and m_surf_h
1079 	if ( !m_initialized ||
1080 			m_width != m_surf_w || m_height != m_surf_h )
1081 	{
1082 		// FIXME:: this can be done in create!
1083 		if ( !m_initialized )
1084 		{
1085 			loadGLExtensions();
1086 		}
1087 
1088 		m_surf_w = m_width;
1089 		m_surf_h = m_height;
1090 
1091 		// we're doing nothing 3d, so the Z-buffer is currently not interesting
1092 		glDisable(GL_DEPTH_TEST);
1093 
1094 		// enable antialiasing for lines
1095 		glEnable(GL_LINE_SMOOTH);
1096 		// enable antialiasing for points
1097 		glEnable(GL_POINT_SMOOTH);
1098 
1099 		// prefer quality to speed
1100 		glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
1101 		glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
1102 
1103 		// enable blending
1104 		glEnable(GL_BLEND);
1105 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1106 		m_last_blendmode = BLENDMODE_ALPHA;
1107 
1108 #ifdef TOBEMIGRATED
1109 		// set lines and points just barely above normal size to get proper results
1110 		glLineWidth(video_config.beamwidth);
1111 		glPointSize(video_config.beamwidth);
1112 #endif
1113 
1114 		// set up a nice simple 2D coordinate system, so GL behaves exactly how we'd like.
1115 		//
1116 		// (0,0)     (w,0)
1117 		//   |~~~~~~~~~|
1118 		//   |         |
1119 		//   |         |
1120 		//   |         |
1121 		//   |_________|
1122 		// (0,h)     (w,h)
1123 
1124 		GLsizei iScale = 1;
1125 
1126 		/*
1127 		    Mac hack: macOS version 10.15 and later flipped from assuming you don't support Retina to
1128 		    assuming you do support Retina.  SDL 2.0.11 is scheduled to fix this, but it's not out yet.
1129 		    So we double-scale everything if you're on 10.15 or later and SDL is not at least version 2.0.11.
1130 		*/
1131 		#if defined(SDLMAME_MACOSX) || defined(OSD_MAC)
1132 		SDL_version sdlVers;
1133 		SDL_GetVersion(&sdlVers);
1134 		// Only do this if SDL is not at least 2.0.11.
1135 		if ((sdlVers.major == 2) && (sdlVers.minor == 0) && (sdlVers.patch < 11))
1136 		{
1137 			// now get the Darwin kernel version
1138 			int dMaj, dMin, dPatch;
1139 			char versStr[64];
1140 			dMaj = dMin = dPatch = 0;
1141 			size_t size = sizeof(versStr);
1142 			int retVal = sysctlbyname("kern.osrelease", versStr, &size, NULL, 0);
1143 			if (retVal == 0)
1144 			{
1145 			  sscanf(versStr, "%d.%d.%d", &dMaj, &dMin, &dPatch);
1146 			  // 10.15 Catalina is Darwin version 19
1147 			  if (dMaj >= 19)
1148 			  {
1149 				  // do the workaround for Retina being forced on
1150 				  osd_printf_verbose("OpenGL: enabling Retina workaround\n");
1151 				  iScale = 2;
1152 			  }
1153 			}
1154 		}
1155 		#endif
1156 
1157 		glViewport(0.0, 0.0, (GLsizei) m_width * iScale, (GLsizei) m_height * iScale);
1158 		glMatrixMode(GL_PROJECTION);
1159 		glLoadIdentity();
1160 		glOrtho(0.0, (GLdouble) m_width, (GLdouble) m_height, 0.0, 0.0, -1.0);
1161 		glMatrixMode(GL_MODELVIEW);
1162 		glLoadIdentity();
1163 
1164 		if ( ! m_initialized )
1165 		{
1166 			glEnableClientState(GL_VERTEX_ARRAY);
1167 			glVertexPointer(2, GL_FLOAT, 0, m_texVerticex); // no VBO, since it's too volatile
1168 
1169 			m_initialized = 1;
1170 		}
1171 	}
1172 
1173 	// compute centering parameters
1174 	vofs = hofs = 0.0f;
1175 
1176 #ifdef TOBEMIGRATED
1177 	if (video_config.centerv || video_config.centerh)
1178 	{
1179 		int ch, cw;
1180 
1181 		ch = m_height;
1182 		cw = m_width;
1183 
1184 		if (video_config.centerv)
1185 		{
1186 			vofs = (ch - m_blit_dim.height()) / 2.0f;
1187 		}
1188 		if (video_config.centerh)
1189 		{
1190 			hofs = (cw - m_blit_dim.width()) / 2.0f;
1191 		}
1192 	}
1193 #else
1194 #endif
1195 
1196 	m_last_hofs = hofs;
1197 	m_last_vofs = vofs;
1198 
1199 	win->m_primlist->acquire_lock();
1200 
1201 	// now draw
1202 	for (render_primitive &prim : *win->m_primlist)
1203 	{
1204 		int i;
1205 
1206 		switch (prim.type)
1207 		{
1208 			/**
1209 			 * Try to stay in one Begin/End block as long as possible,
1210 			 * since entering and leaving one is most expensive..
1211 			 */
1212 			case render_primitive::LINE:
1213 				#if !USE_WIN32_STYLE_LINES
1214 				// check if it's really a point
1215 				if (((prim.bounds.x1 - prim.bounds.x0) == 0) && ((prim.bounds.y1 - prim.bounds.y0) == 0))
1216 				{
1217 					curPrimitive=GL_POINTS;
1218 				} else {
1219 					curPrimitive=GL_LINES;
1220 				}
1221 
1222 				if(pendingPrimitive!=GL_NO_PRIMITIVE && pendingPrimitive!=curPrimitive)
1223 				{
1224 					glEnd();
1225 					pendingPrimitive=GL_NO_PRIMITIVE;
1226 				}
1227 
1228 						if ( pendingPrimitive==GL_NO_PRIMITIVE )
1229 				{
1230 							set_blendmode(PRIMFLAG_GET_BLENDMODE(prim.flags));
1231 				}
1232 
1233 				glColor4f(prim.color.r, prim.color.g, prim.color.b, prim.color.a);
1234 
1235 				if(pendingPrimitive!=curPrimitive)
1236 				{
1237 					glLineWidth(prim.width);
1238 					glBegin(curPrimitive);
1239 					pendingPrimitive=curPrimitive;
1240 				}
1241 
1242 				// check if it's really a point
1243 				if (curPrimitive==GL_POINTS)
1244 				{
1245 					glVertex2f(prim.bounds.x0+hofs, prim.bounds.y0+vofs);
1246 				}
1247 				else
1248 				{
1249 					glVertex2f(prim.bounds.x0+hofs, prim.bounds.y0+vofs);
1250 					glVertex2f(prim.bounds.x1+hofs, prim.bounds.y1+vofs);
1251 				}
1252 				#else
1253 				{
1254 					const line_aa_step *step = line_aa_4step;
1255 					render_bounds b0, b1;
1256 					float r, g, b, a;
1257 					float effwidth;
1258 
1259 					// we're not gonna play fancy here.  close anything pending and let's go.
1260 					if (pendingPrimitive!=GL_NO_PRIMITIVE && pendingPrimitive!=curPrimitive)
1261 					{
1262 						glEnd();
1263 						pendingPrimitive=GL_NO_PRIMITIVE;
1264 					}
1265 
1266 					set_blendmode(sdl, PRIMFLAG_GET_BLENDMODE(prim.flags));
1267 
1268 					// compute the effective width based on the direction of the line
1269 					effwidth = prim.width();
1270 					if (effwidth < 0.5f)
1271 						effwidth = 0.5f;
1272 
1273 					// determine the bounds of a quad to draw this line
1274 					render_line_to_quad(&prim.bounds, effwidth, 0.0f, &b0, &b1);
1275 
1276 					// fix window position
1277 					b0.x0 += hofs;
1278 					b0.x1 += hofs;
1279 					b1.x0 += hofs;
1280 					b1.x1 += hofs;
1281 					b0.y0 += vofs;
1282 					b0.y1 += vofs;
1283 					b1.y0 += vofs;
1284 					b1.y1 += vofs;
1285 
1286 					// iterate over AA steps
1287 					for (step = PRIMFLAG_GET_ANTIALIAS(prim.flags) ? line_aa_4step : line_aa_1step; step->weight != 0; step++)
1288 					{
1289 						glBegin(GL_TRIANGLE_STRIP);
1290 
1291 						// rotate the unit vector by 135 degrees and add to point 0
1292 						glVertex2f(b0.x0 + step->xoffs, b0.y0 + step->yoffs);
1293 
1294 						// rotate the unit vector by -135 degrees and add to point 0
1295 						glVertex2f(b0.x1 + step->xoffs, b0.y1 + step->yoffs);
1296 
1297 						// rotate the unit vector by 45 degrees and add to point 1
1298 						glVertex2f(b1.x0 + step->xoffs, b1.y0 + step->yoffs);
1299 
1300 						// rotate the unit vector by -45 degrees and add to point 1
1301 						glVertex2f(b1.x1 + step->xoffs, b1.y1 + step->yoffs);
1302 
1303 						// determine the color of the line
1304 						r = (prim.color.r * step->weight);
1305 						g = (prim.color.g * step->weight);
1306 						b = (prim.color.b * step->weight);
1307 						a = (prim.color.a * 255.0f);
1308 						if (r > 1.0) r = 1.0;
1309 						if (g > 1.0) g = 1.0;
1310 						if (b > 1.0) b = 1.0;
1311 						if (a > 1.0) a = 1.0;
1312 						glColor4f(r, g, b, a);
1313 
1314 //                      texture = texture_update(window, &prim, 0);
1315 //                      if (texture) printf("line has texture!\n");
1316 
1317 						// if we have a texture to use for the vectors, use it here
1318 						#if 0
1319 						if (d3d->vector_texture != nullptr)
1320 						{
1321 							printf("SDL: textured lines unsupported\n");
1322 							vertex[0].u0 = d3d->vector_texture->ustart;
1323 							vertex[0].v0 = d3d->vector_texture->vstart;
1324 
1325 							vertex[2].u0 = d3d->vector_texture->ustop;
1326 							vertex[2].v0 = d3d->vector_texture->vstart;
1327 
1328 							vertex[1].u0 = d3d->vector_texture->ustart;
1329 							vertex[1].v0 = d3d->vector_texture->vstop;
1330 
1331 							vertex[3].u0 = d3d->vector_texture->ustop;
1332 							vertex[3].v0 = d3d->vector_texture->vstop;
1333 						}
1334 						#endif
1335 						glEnd();
1336 					}
1337 				}
1338 				#endif
1339 				break;
1340 
1341 			case render_primitive::QUAD:
1342 
1343 				if(pendingPrimitive!=GL_NO_PRIMITIVE)
1344 				{
1345 					glEnd();
1346 					pendingPrimitive=GL_NO_PRIMITIVE;
1347 				}
1348 
1349 				glColor4f(prim.color.r, prim.color.g, prim.color.b, prim.color.a);
1350 
1351 				set_blendmode(PRIMFLAG_GET_BLENDMODE(prim.flags));
1352 
1353 				texture = texture_update(&prim, 0);
1354 
1355 				if ( texture && texture->type==TEXTURE_TYPE_SHADER )
1356 				{
1357 					for(i=0; i<m_glsl_program_num; i++)
1358 					{
1359 						if ( i==m_glsl_program_mb2sc )
1360 						{
1361 							// i==glsl_program_mb2sc -> transformation mamebm->scrn
1362 							m_texVerticex[0]=prim.bounds.x0 + hofs;
1363 							m_texVerticex[1]=prim.bounds.y0 + vofs;
1364 							m_texVerticex[2]=prim.bounds.x1 + hofs;
1365 							m_texVerticex[3]=prim.bounds.y0 + vofs;
1366 							m_texVerticex[4]=prim.bounds.x1 + hofs;
1367 							m_texVerticex[5]=prim.bounds.y1 + vofs;
1368 							m_texVerticex[6]=prim.bounds.x0 + hofs;
1369 							m_texVerticex[7]=prim.bounds.y1 + vofs;
1370 						} else {
1371 							// 1:1 tex coord CCW (0/0) (1/0) (1/1) (0/1) on texture dimensions
1372 							m_texVerticex[0]=(GLfloat)0.0;
1373 							m_texVerticex[1]=(GLfloat)0.0;
1374 							m_texVerticex[2]=(GLfloat)m_width;
1375 							m_texVerticex[3]=(GLfloat)0.0;
1376 							m_texVerticex[4]=(GLfloat)m_width;
1377 							m_texVerticex[5]=(GLfloat)m_height;
1378 							m_texVerticex[6]=(GLfloat)0.0;
1379 							m_texVerticex[7]=(GLfloat)m_height;
1380 						}
1381 
1382 						if(i>0) // first fetch already done
1383 						{
1384 							texture = texture_update(&prim, i);
1385 						}
1386 						glDrawArrays(GL_QUADS, 0, 4);
1387 					}
1388 				} else {
1389 					m_texVerticex[0]=prim.bounds.x0 + hofs;
1390 					m_texVerticex[1]=prim.bounds.y0 + vofs;
1391 					m_texVerticex[2]=prim.bounds.x1 + hofs;
1392 					m_texVerticex[3]=prim.bounds.y0 + vofs;
1393 					m_texVerticex[4]=prim.bounds.x1 + hofs;
1394 					m_texVerticex[5]=prim.bounds.y1 + vofs;
1395 					m_texVerticex[6]=prim.bounds.x0 + hofs;
1396 					m_texVerticex[7]=prim.bounds.y1 + vofs;
1397 
1398 					glDrawArrays(GL_QUADS, 0, 4);
1399 				}
1400 
1401 				if ( texture )
1402 				{
1403 					texture_disable(texture);
1404 					texture=nullptr;
1405 				}
1406 				break;
1407 
1408 			default:
1409 				throw emu_fatalerror("Unexpected render_primitive type");
1410 		}
1411 	}
1412 
1413 	if(pendingPrimitive!=GL_NO_PRIMITIVE)
1414 	{
1415 		glEnd();
1416 		pendingPrimitive=GL_NO_PRIMITIVE;
1417 	}
1418 
1419 	win->m_primlist->release_lock();
1420 	m_init_context = 0;
1421 
1422 	m_gl_context->SwapBuffer();
1423 
1424 	return 0;
1425 }
1426 
1427 //============================================================
1428 //  texture handling
1429 //============================================================
1430 
1431 static const char * texfmt_to_string[9] = {
1432 		"ARGB32",
1433 		"RGB32",
1434 		"RGB32_PALETTED",
1435 		"YUV16",
1436 		"YUV16_PALETTED",
1437 		"PALETTE16",
1438 		"RGB15",
1439 		"RGB15_PALETTE",
1440 		"PALETTE16A"
1441 		};
1442 
1443 //
1444 // Note: if you change the following array order, change the matching defines in texsrc.h
1445 //
1446 
1447 enum { SDL_TEXFORMAT_SRC_EQUALS_DEST, SDL_TEXFORMAT_SRC_HAS_PALETTE };
1448 
1449 static const GLint texture_copy_properties[9][2] = {
1450 	{ true,  false },   // SDL_TEXFORMAT_ARGB32
1451 	{ true,  false },   // SDL_TEXFORMAT_RGB32
1452 	{ true,  true  },   // SDL_TEXFORMAT_RGB32_PALETTED
1453 	{ false, false },   // SDL_TEXFORMAT_YUY16
1454 	{ false, true  },   // SDL_TEXFORMAT_YUY16_PALETTED
1455 	{ false, true  },   // SDL_TEXFORMAT_PALETTE16
1456 	{ true,  false },   // SDL_TEXFORMAT_RGB15
1457 	{ true,  true  },   // SDL_TEXFORMAT_RGB15_PALETTED
1458 	{ false, true  }    // SDL_TEXFORMAT_PALETTE16A
1459 };
1460 
1461 //============================================================
1462 //  texture_compute_size and type
1463 //============================================================
1464 
1465 //
1466 // glBufferData to push a nocopy texture to the GPU is slower than TexSubImage2D,
1467 // so don't use PBO here
1468 //
1469 // we also don't want to use PBO's in the case of nocopy==true,
1470 // since we now might have GLSL shaders - this decision simplifies out life ;-)
1471 //
texture_compute_type_subroutine(const render_texinfo * texsource,ogl_texture_info * texture,uint32_t flags)1472 void renderer_ogl::texture_compute_type_subroutine(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags)
1473 {
1474 	texture->type = TEXTURE_TYPE_NONE;
1475 	texture->nocopy = false;
1476 
1477 	if ( texture->type == TEXTURE_TYPE_NONE &&
1478 			!PRIMFLAG_GET_SCREENTEX(flags))
1479 	{
1480 		texture->type = TEXTURE_TYPE_PLAIN;
1481 				texture->texTarget = (m_usetexturerect)?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D;
1482 				texture->texpow2   = (m_usetexturerect)?0:m_texpoweroftwo;
1483 	}
1484 
1485 	if ( texture->type == TEXTURE_TYPE_NONE && m_useglsl &&
1486 			texture->xprescale == 1 && texture->yprescale == 1 &&
1487 			texsource->rowpixels <= m_texture_max_width )
1488 		{
1489 			texture->type      = TEXTURE_TYPE_SHADER;
1490 			texture->texTarget = GL_TEXTURE_2D;
1491 			texture->texpow2   = m_texpoweroftwo;
1492 		}
1493 
1494 	// determine if we can skip the copy step
1495 	// if this was not already decided by the shader condition above
1496 	if    ( texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_EQUALS_DEST] &&
1497 			!texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_HAS_PALETTE] &&
1498 			texture->xprescale == 1 && texture->yprescale == 1 &&
1499 			!texture->borderpix && !texsource->palette &&
1500 			texsource->rowpixels <= m_texture_max_width )
1501 	{
1502 		texture->nocopy = true;
1503 	}
1504 
1505 	if( texture->type == TEXTURE_TYPE_NONE &&
1506 		m_usepbo && !texture->nocopy )
1507 	{
1508 		texture->type      = TEXTURE_TYPE_DYNAMIC;
1509 		texture->texTarget = (m_usetexturerect)?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D;
1510 		texture->texpow2   = (m_usetexturerect)?0:m_texpoweroftwo;
1511 	}
1512 
1513 	if( texture->type == TEXTURE_TYPE_NONE )
1514 	{
1515 		texture->type      = TEXTURE_TYPE_SURFACE;
1516 		texture->texTarget = (m_usetexturerect)?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D;
1517 		texture->texpow2   = (m_usetexturerect)?0:m_texpoweroftwo;
1518 	}
1519 }
1520 
get_valid_pow2_value(int v,int needPow2)1521 static inline int get_valid_pow2_value(int v, int needPow2)
1522 {
1523 	return (needPow2)?gl_round_to_pow2(v):v;
1524 }
1525 
texture_compute_size_subroutine(ogl_texture_info * texture,uint32_t flags,uint32_t width,uint32_t height,int * p_width,int * p_height,int * p_width_create,int * p_height_create)1526 void renderer_ogl::texture_compute_size_subroutine(ogl_texture_info *texture, uint32_t flags,
1527 											uint32_t width, uint32_t height,
1528 											int* p_width, int* p_height, int* p_width_create, int* p_height_create)
1529 {
1530 	int width_create;
1531 	int height_create;
1532 
1533 	if ( texture->texpow2 )
1534 		{
1535 				width_create  = gl_round_to_pow2 (width);
1536 				height_create = gl_round_to_pow2 (height);
1537 		} else if ( texture->type==TEXTURE_TYPE_SHADER )
1538 		{
1539 				/**
1540 				 * at least use a multiple of 8 for shader .. just in case
1541 				 */
1542 				width_create  = ( width  & ~0x07 ) + ( (width  & 0x07)? 8 : 0 ) ;
1543 				height_create = ( height & ~0x07 ) + ( (height & 0x07)? 8 : 0 ) ;
1544 		} else {
1545 				width_create  = width  ;
1546 				height_create = height ;
1547 		}
1548 
1549 	// don't prescale above max texture size
1550 	while (texture->xprescale > 1 && width_create * texture->xprescale > m_texture_max_width)
1551 		texture->xprescale--;
1552 	while (texture->yprescale > 1 && height_create * texture->yprescale > m_texture_max_height)
1553 		texture->yprescale--;
1554 
1555 	auto win = assert_window();
1556 	if (PRIMFLAG_GET_SCREENTEX(flags) && (texture->xprescale != win->prescale() || texture->yprescale != win->prescale()))
1557 		osd_printf_warning("SDL: adjusting prescale from %dx%d to %dx%d\n", win->prescale(), win->prescale(), texture->xprescale, texture->yprescale);
1558 
1559 	width  *= texture->xprescale;
1560 	height *= texture->yprescale;
1561 	width_create  *= texture->xprescale;
1562 	height_create *= texture->yprescale;
1563 
1564 	// adjust the size for the border (must do this *after* the power of 2 clamp to satisfy
1565 	// OpenGL semantics)
1566 	if (texture->borderpix)
1567 	{
1568 		width += 2;
1569 		height += 2;
1570 		width_create += 2;
1571 		height_create += 2;
1572 	}
1573 		*p_width=width;
1574 		*p_height=height;
1575 		*p_width_create=width_create;
1576 		*p_height_create=height_create;
1577 }
1578 
texture_compute_size_type(const render_texinfo * texsource,ogl_texture_info * texture,uint32_t flags)1579 void renderer_ogl::texture_compute_size_type(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags)
1580 {
1581 	int finalheight, finalwidth;
1582 	int finalheight_create, finalwidth_create;
1583 
1584 	// if we're not wrapping, add a 1 pixel border on all sides
1585 	texture->borderpix = 0; //!(texture->flags & PRIMFLAG_TEXWRAP_MASK);
1586 	if (PRIMFLAG_GET_SCREENTEX(flags))
1587 	{
1588 		texture->borderpix = 0; // don't border the screen right now, there's a bug
1589 	}
1590 
1591 	texture_compute_type_subroutine(texsource, texture, flags);
1592 
1593 	texture_compute_size_subroutine(texture, flags, texsource->width, texsource->height,
1594 									&finalwidth, &finalheight, &finalwidth_create, &finalheight_create);
1595 
1596 	// if we added pixels for the border, and that just barely pushed us over, take it back
1597 	if (texture->borderpix &&
1598 		((finalwidth > m_texture_max_width && finalwidth - 2 <= m_texture_max_width) ||
1599 			(finalheight > m_texture_max_height && finalheight - 2 <= m_texture_max_height)))
1600 	{
1601 		texture->borderpix = false;
1602 
1603 		texture_compute_type_subroutine(texsource, texture, flags);
1604 
1605 		texture_compute_size_subroutine(texture, flags, texsource->width, texsource->height,
1606 										&finalwidth, &finalheight, &finalwidth_create, &finalheight_create);
1607 	}
1608 
1609 	// if we're above the max width/height, do what?
1610 	if (finalwidth_create > m_texture_max_width || finalheight_create > m_texture_max_height)
1611 	{
1612 		static int printed = false;
1613 		if (!printed)
1614 			osd_printf_warning("Texture too big! (wanted: %dx%d, max is %dx%d)\n", finalwidth_create, finalheight_create, m_texture_max_width, m_texture_max_height);
1615 		printed = true;
1616 	}
1617 
1618 	if(!texture->nocopy || texture->type==TEXTURE_TYPE_DYNAMIC || texture->type==TEXTURE_TYPE_SHADER ||
1619 		// any of the mame core's device generated bitmap types:
1620 		texture->format==SDL_TEXFORMAT_RGB32  ||
1621 		texture->format==SDL_TEXFORMAT_RGB32_PALETTED  ||
1622 		texture->format==SDL_TEXFORMAT_RGB15  ||
1623 		texture->format==SDL_TEXFORMAT_RGB15_PALETTED  ||
1624 		texture->format==SDL_TEXFORMAT_PALETTE16  ||
1625 		texture->format==SDL_TEXFORMAT_PALETTE16A
1626 		)
1627 	{
1628 		osd_printf_verbose("GL texture: copy %d, shader %d, dynamic %d, %dx%d %dx%d [%s, Equal: %d, Palette: %d,\n"
1629 					"            scale %dx%d, border %d, pitch %d,%d/%d], bytes/pix %d\n",
1630 			!texture->nocopy, texture->type==TEXTURE_TYPE_SHADER, texture->type==TEXTURE_TYPE_DYNAMIC,
1631 			finalwidth, finalheight, finalwidth_create, finalheight_create,
1632 			texfmt_to_string[texture->format],
1633 			(int)texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_EQUALS_DEST],
1634 			(int)texture_copy_properties[texture->format][SDL_TEXFORMAT_SRC_HAS_PALETTE],
1635 			texture->xprescale, texture->yprescale,
1636 			texture->borderpix, texsource->rowpixels, finalwidth, m_texture_max_width,
1637 			(int)sizeof(uint32_t)
1638 			);
1639 	}
1640 
1641 	// set the final values
1642 	texture->rawwidth = finalwidth;
1643 	texture->rawheight = finalheight;
1644 	texture->rawwidth_create = finalwidth_create;
1645 	texture->rawheight_create = finalheight_create;
1646 }
1647 
1648 //============================================================
1649 //  texture_create
1650 //============================================================
1651 
gl_checkFramebufferStatus()1652 static int gl_checkFramebufferStatus()
1653 {
1654 	GLenum status;
1655 	status=(GLenum)pfn_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
1656 	switch(status) {
1657 		case GL_FRAMEBUFFER_COMPLETE_EXT:
1658 			return 0;
1659 		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
1660 			osd_printf_error("GL FBO: incomplete,incomplete attachment\n");
1661 			return -1;
1662 		case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
1663 			osd_printf_error("GL FBO: Unsupported framebuffer format\n");
1664 			return -1;
1665 		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
1666 			osd_printf_error("GL FBO: incomplete,missing attachment\n");
1667 			return -1;
1668 		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
1669 			osd_printf_error("GL FBO: incomplete,attached images must have same dimensions\n");
1670 			return -1;
1671 		case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
1672 				osd_printf_error("GL FBO: incomplete,attached images must have same format\n");
1673 			return -1;
1674 		case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
1675 			osd_printf_error("GL FBO: incomplete,missing draw buffer\n");
1676 			return -1;
1677 		case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
1678 			osd_printf_error("GL FBO: incomplete,missing read buffer\n");
1679 			return -1;
1680 #ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
1681 		case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
1682 			osd_printf_error("GL FBO: incomplete, duplicate attachment\n");
1683 			return -1;
1684 #endif
1685 		case 0:
1686 			osd_printf_error("GL FBO: incomplete, implementation fault\n");
1687 			return -1;
1688 		default:
1689 			osd_printf_error("GL FBO: incomplete, implementation ERROR\n");
1690 			/* fall through */
1691 	}
1692 	return -1;
1693 }
1694 
texture_fbo_create(uint32_t text_unit,uint32_t text_name,uint32_t fbo_name,int width,int height)1695 static int texture_fbo_create(uint32_t text_unit, uint32_t text_name, uint32_t fbo_name, int width, int height)
1696 {
1697 	pfn_glActiveTexture(text_unit);
1698 	pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_name);
1699 	glBindTexture(GL_TEXTURE_2D, text_name);
1700 	{
1701 		GLint _width, _height;
1702 		if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
1703 						0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &_width, &_height, 1) )
1704 		{
1705 			osd_printf_error("cannot create fbo texture, req: %dx%d, avail: %dx%d - bail out\n",
1706 						width, height, (int)_width, (int)_height);
1707 			return -1;
1708 		}
1709 
1710 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
1711 				0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr );
1712 	}
1713 	// non-screen textures will never be filtered
1714 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1715 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1716 
1717 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1718 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1719 
1720 	pfn_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
1721 					GL_TEXTURE_2D, text_name, 0);
1722 
1723 	if ( gl_checkFramebufferStatus() )
1724 	{
1725 		osd_printf_error("FBO error fbo texture - bail out\n");
1726 		return -1;
1727 	}
1728 
1729 	return 0;
1730 }
1731 
texture_shader_create(const render_texinfo * texsource,ogl_texture_info * texture,uint32_t flags)1732 int renderer_ogl::texture_shader_create(const render_texinfo *texsource, ogl_texture_info *texture, uint32_t flags)
1733 {
1734 	int uniform_location;
1735 	int i;
1736 	int surf_w_pow2  = get_valid_pow2_value (m_blit_dim.width(), texture->texpow2);
1737 	int surf_h_pow2  = get_valid_pow2_value (m_blit_dim.height(), texture->texpow2);
1738 
1739 	assert ( texture->type==TEXTURE_TYPE_SHADER );
1740 
1741 	GL_CHECK_ERROR_QUIET();
1742 
1743 	if( m_glsl_program_num > 1 )
1744 	{
1745 		// multipass mode
1746 		assert(m_usefbo);
1747 
1748 		// GL_TEXTURE3 GLSL Uniforms
1749 		texture->mpass_dest_idx = 0;
1750 		texture->mpass_textureunit[0] = GL_TEXTURE3;
1751 		texture->mpass_textureunit[1] = GL_TEXTURE2;
1752 	}
1753 
1754 	for(i=0; i<m_glsl_program_num; i++)
1755 	{
1756 		if ( i<=m_glsl_program_mb2sc )
1757 		{
1758 			m_glsl_program[i] = glsl_shader_get_program_mamebm(glsl_shader_feature, i);
1759 		} else {
1760 			m_glsl_program[i] = glsl_shader_get_program_scrn(i-1-m_glsl_program_mb2sc);
1761 		}
1762 		pfn_glUseProgramObjectARB(m_glsl_program[i]);
1763 
1764 		if ( i<=m_glsl_program_mb2sc )
1765 		{
1766 			// GL_TEXTURE0 GLSL Uniforms
1767 			uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture");
1768 			pfn_glUniform1iARB(uniform_location, 0);
1769 			GL_CHECK_ERROR_NORMAL();
1770 		}
1771 
1772 		{
1773 			GLfloat color_texture_sz[2] = { (GLfloat)texture->rawwidth, (GLfloat)texture->rawheight };
1774 			uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_sz");
1775 			pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_sz[0]));
1776 			GL_CHECK_ERROR_NORMAL();
1777 		}
1778 
1779 		GLfloat color_texture_pow2_sz[2] = { (GLfloat)texture->rawwidth_create, (GLfloat)texture->rawheight_create };
1780 		uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "color_texture_pow2_sz");
1781 		pfn_glUniform2fvARB(uniform_location, 1, &(color_texture_pow2_sz[0]));
1782 		GL_CHECK_ERROR_NORMAL();
1783 
1784 		GLfloat screen_texture_sz[2] = { (GLfloat) m_blit_dim.width(), (GLfloat) m_blit_dim.height() };
1785 		uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_sz");
1786 		pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_sz[0]));
1787 		GL_CHECK_ERROR_NORMAL();
1788 
1789 		GLfloat screen_texture_pow2_sz[2] = { (GLfloat)surf_w_pow2, (GLfloat)surf_h_pow2 };
1790 		uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[i], "screen_texture_pow2_sz");
1791 		pfn_glUniform2fvARB(uniform_location, 1, &(screen_texture_pow2_sz[0]));
1792 		GL_CHECK_ERROR_NORMAL();
1793 	}
1794 
1795 	pfn_glUseProgramObjectARB(m_glsl_program[0]); // start with 1st shader
1796 
1797 	if( m_glsl_program_num > 1 )
1798 	{
1799 		// multipass mode
1800 		// GL_TEXTURE2/GL_TEXTURE3
1801 		pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_mamebm[0]);
1802 		glGenTextures(2, (GLuint *)&texture->mpass_texture_mamebm[0]);
1803 
1804 		for (i=0; i<2; i++)
1805 		{
1806 			if ( texture_fbo_create(texture->mpass_textureunit[i],
1807 									texture->mpass_texture_mamebm[i],
1808 						texture->mpass_fbo_mamebm[i],
1809 						texture->rawwidth_create, texture->rawheight_create) )
1810 			{
1811 				return -1;
1812 			}
1813 		}
1814 
1815 		pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
1816 
1817 		osd_printf_verbose("GL texture: mpass mame-bmp   2x %dx%d (pow2 %dx%d)\n",
1818 			texture->rawwidth, texture->rawheight, texture->rawwidth_create, texture->rawheight_create);
1819 	}
1820 
1821 	if( m_glsl_program_num > 1 && m_glsl_program_mb2sc < m_glsl_program_num - 1 )
1822 	{
1823 		// multipass mode
1824 		// GL_TEXTURE2/GL_TEXTURE3
1825 		pfn_glGenFramebuffers(2, (GLuint *)&texture->mpass_fbo_scrn[0]);
1826 		glGenTextures(2, (GLuint *)&texture->mpass_texture_scrn[0]);
1827 
1828 		for (i=0; i<2; i++)
1829 		{
1830 			if ( texture_fbo_create(texture->mpass_textureunit[i],
1831 									texture->mpass_texture_scrn[i],
1832 						texture->mpass_fbo_scrn[i],
1833 						surf_w_pow2, surf_h_pow2) )
1834 			{
1835 				return -1;
1836 			}
1837 		}
1838 
1839 		osd_printf_verbose("GL texture: mpass screen-bmp 2x %dx%d (pow2 %dx%d)\n",
1840 			m_width, m_height, surf_w_pow2, surf_h_pow2);
1841 	}
1842 
1843 	// GL_TEXTURE0
1844 	// get a name for this texture
1845 	glGenTextures(1, (GLuint *)&texture->texture);
1846 	pfn_glActiveTexture(GL_TEXTURE0);
1847 	glBindTexture(GL_TEXTURE_2D, texture->texture);
1848 
1849 	glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth_create);
1850 
1851 	uint32_t * dummy = nullptr;
1852 	GLint _width, _height;
1853 	if ( gl_texture_check_size(GL_TEXTURE_2D, 0, GL_RGBA8,
1854 					texture->rawwidth_create, texture->rawheight_create,
1855 					0,
1856 					GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
1857 					&_width, &_height, 1) )
1858 	{
1859 		osd_printf_error("cannot create bitmap texture, req: %dx%d, avail: %dx%d - bail out\n",
1860 			texture->rawwidth_create, texture->rawheight_create, (int)_width, (int)_height);
1861 		return -1;
1862 	}
1863 
1864 	dummy = (uint32_t *) malloc(texture->rawwidth_create * texture->rawheight_create * sizeof(uint32_t));
1865 	memset(dummy, 0, texture->rawwidth_create * texture->rawheight_create * sizeof(uint32_t));
1866 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
1867 			texture->rawwidth_create, texture->rawheight_create,
1868 			0,
1869 			GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, dummy);
1870 			glFinish(); // should not be necessary, .. but make sure we won't access the memory after free
1871 	free(dummy);
1872 
1873 	if ((PRIMFLAG_GET_SCREENTEX(flags)) && video_config.filter)
1874 	{
1875 		assert( glsl_shader_feature == GLSL_SHADER_FEAT_PLAIN );
1876 
1877 		// screen textures get the user's choice of filtering
1878 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1879 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1880 	}
1881 	else
1882 	{
1883 		// non-screen textures will never be filtered
1884 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1885 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1886 	}
1887 
1888 	// set wrapping mode appropriately
1889 	if (texture->flags & PRIMFLAG_TEXWRAP_MASK)
1890 	{
1891 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1892 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1893 	}
1894 	else
1895 	{
1896 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1897 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1898 	}
1899 
1900 	GL_CHECK_ERROR_NORMAL();
1901 
1902 	return 0;
1903 }
1904 
texture_create(const render_texinfo * texsource,uint32_t flags)1905 ogl_texture_info *renderer_ogl::texture_create(const render_texinfo *texsource, uint32_t flags)
1906 {
1907 	ogl_texture_info *texture;
1908 
1909 	// allocate a new texture
1910 	texture = new ogl_texture_info;
1911 
1912 	// fill in the core data
1913 	texture->hash = texture_compute_hash(texsource, flags);
1914 	texture->flags = flags;
1915 	texture->texinfo = *texsource;
1916 	texture->texinfo.seqid = -1; // force set data
1917 	if (PRIMFLAG_GET_SCREENTEX(flags))
1918 	{
1919 		auto win = assert_window();
1920 		texture->xprescale = win->prescale();
1921 		texture->yprescale = win->prescale();
1922 	}
1923 	else
1924 	{
1925 		texture->xprescale = 1;
1926 		texture->yprescale = 1;
1927 	}
1928 
1929 	// set the texture_format
1930 		//
1931 		// src/emu/validity.c:validate_display() states,
1932 		// an emulated driver can only produce
1933 		//      BITMAP_FORMAT_IND16 and BITMAP_FORMAT_RGB32
1934 		// where only the first original paletted.
1935 		//
1936 		// other paletted formats, i.e.:
1937 		//   SDL_TEXFORMAT_RGB32_PALETTED, SDL_TEXFORMAT_RGB15_PALETTED and SDL_TEXFORMAT_YUY16_PALETTED
1938 		// add features like brightness etc by the mame core
1939 		//
1940 		// all palette lookup may be implemented using shaders later on ..
1941 		// that's why we keep the EQUAL flag TRUE, for all original true color bitmaps.
1942 		//
1943 	switch (PRIMFLAG_GET_TEXFORMAT(flags))
1944 	{
1945 		case TEXFORMAT_ARGB32:
1946 			texture->format = SDL_TEXFORMAT_ARGB32;
1947 			break;
1948 		case TEXFORMAT_RGB32:
1949 			if (texsource->palette != nullptr)
1950 				texture->format = SDL_TEXFORMAT_RGB32_PALETTED;
1951 			else
1952 				texture->format = SDL_TEXFORMAT_RGB32;
1953 			break;
1954 		case TEXFORMAT_PALETTE16:
1955 			texture->format = SDL_TEXFORMAT_PALETTE16;
1956 			break;
1957 		case TEXFORMAT_YUY16:
1958 			if (texsource->palette != nullptr)
1959 				texture->format = SDL_TEXFORMAT_YUY16_PALETTED;
1960 			else
1961 				texture->format = SDL_TEXFORMAT_YUY16;
1962 			break;
1963 
1964 		default:
1965 			osd_printf_error("Unknown textureformat %d\n", PRIMFLAG_GET_TEXFORMAT(flags));
1966 	}
1967 
1968 	// compute the size
1969 	texture_compute_size_type(texsource, texture, flags);
1970 
1971 	texture->pbo=0;
1972 
1973 	if ( texture->type != TEXTURE_TYPE_SHADER && m_useglsl)
1974 	{
1975 		pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
1976 	}
1977 
1978 	if ( texture->type==TEXTURE_TYPE_SHADER )
1979 	{
1980 		if ( texture_shader_create(texsource, texture, flags) )
1981 		{
1982 			delete texture;
1983 			return nullptr;
1984 		}
1985 	}
1986 	else
1987 	{
1988 		// get a name for this texture
1989 		glGenTextures(1, (GLuint *)&texture->texture);
1990 
1991 		glEnable(texture->texTarget);
1992 
1993 		// make sure we're operating on *this* texture
1994 		glBindTexture(texture->texTarget, texture->texture);
1995 
1996 		// this doesn't actually upload, it just sets up the PBO's parameters
1997 		glTexImage2D(texture->texTarget, 0, GL_RGBA8,
1998 				texture->rawwidth_create, texture->rawheight_create,
1999 				texture->borderpix ? 1 : 0,
2000 				GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
2001 
2002 		if ((PRIMFLAG_GET_SCREENTEX(flags)) && video_config.filter)
2003 		{
2004 			// screen textures get the user's choice of filtering
2005 			glTexParameteri(texture->texTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2006 			glTexParameteri(texture->texTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2007 		}
2008 		else
2009 		{
2010 			// non-screen textures will never be filtered
2011 			glTexParameteri(texture->texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2012 			glTexParameteri(texture->texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2013 		}
2014 
2015 		if( texture->texTarget==GL_TEXTURE_RECTANGLE_ARB )
2016 		{
2017 			// texture rectangles can't wrap
2018 			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2019 			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2020 		} else {
2021 			// set wrapping mode appropriately
2022 			if (texture->flags & PRIMFLAG_TEXWRAP_MASK)
2023 			{
2024 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
2025 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
2026 			}
2027 			else
2028 			{
2029 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2030 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2031 			}
2032 		}
2033 	}
2034 
2035 	if ( texture->type == TEXTURE_TYPE_DYNAMIC )
2036 	{
2037 		assert(m_usepbo);
2038 
2039 		// create the PBO
2040 		pfn_glGenBuffers(1, (GLuint *)&texture->pbo);
2041 
2042 		pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo);
2043 
2044 		// set up the PBO dimension, ..
2045 		pfn_glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB,
2046 							texture->rawwidth * texture->rawheight * sizeof(uint32_t),
2047 					nullptr, GL_STREAM_DRAW);
2048 	}
2049 
2050 	if ( !texture->nocopy && texture->type!=TEXTURE_TYPE_DYNAMIC )
2051 	{
2052 		texture->data = (uint32_t *) malloc(texture->rawwidth* texture->rawheight * sizeof(uint32_t));
2053 		texture->data_own=true;
2054 	}
2055 
2056 	// add us to the texture list
2057 	if (m_texhash[texture->hash] == nullptr)
2058 		m_texhash[texture->hash] = texture;
2059 	else
2060 	{
2061 		int i;
2062 		for (i = HASH_SIZE; i < HASH_SIZE + OVERFLOW_SIZE; i++)
2063 			if (m_texhash[i] == nullptr)
2064 			{
2065 				m_texhash[i] = texture;
2066 				break;
2067 			}
2068 		if ((HASH_SIZE + OVERFLOW_SIZE) <= i)
2069 			throw emu_fatalerror("renderer_ogl::texture_create: texture hash exhausted ...");
2070 	}
2071 
2072 	if (m_usevbo)
2073 	{
2074 		// Generate And Bind The Texture Coordinate Buffer
2075 		pfn_glGenBuffers( 1, &(texture->texCoordBufferName) );
2076 		pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName );
2077 		// Load The Data
2078 		pfn_glBufferData( GL_ARRAY_BUFFER_ARB, 4*2*sizeof(GLfloat), texture->texCoord, GL_STREAM_DRAW );
2079 		glTexCoordPointer( 2, GL_FLOAT, 0, (char *) nullptr ); // we are using ARB VBO buffers
2080 	}
2081 	else
2082 	{
2083 		glTexCoordPointer(2, GL_FLOAT, 0, texture->texCoord);
2084 	}
2085 
2086 	return texture;
2087 }
2088 
2089 //============================================================
2090 //  copyline_palette16
2091 //============================================================
2092 
copyline_palette16(uint32_t * dst,const uint16_t * src,int width,const rgb_t * palette,int xborderpix,int xprescale)2093 static inline void copyline_palette16(uint32_t *dst, const uint16_t *src, int width, const rgb_t *palette, int xborderpix, int xprescale)
2094 {
2095 	int x;
2096 
2097 	assert(xborderpix == 0 || xborderpix == 1);
2098 	if (xborderpix)
2099 		*dst++ = 0xff000000 | palette[*src];
2100 	for (x = 0; x < width; x++)
2101 	{
2102 		int srcpix = *src++;
2103 		uint32_t dstval = 0xff000000 | palette[srcpix];
2104 		for (int x2 = 0; x2 < xprescale; x2++)
2105 			*dst++ = dstval;
2106 	}
2107 	if (xborderpix)
2108 		*dst++ = 0xff000000 | palette[*--src];
2109 }
2110 
2111 
2112 
2113 //============================================================
2114 //  copyline_rgb32
2115 //============================================================
2116 
copyline_rgb32(uint32_t * dst,const uint32_t * src,int width,const rgb_t * palette,int xborderpix,int xprescale)2117 static inline void copyline_rgb32(uint32_t *dst, const uint32_t *src, int width, const rgb_t *palette, int xborderpix, int xprescale)
2118 {
2119 	int x;
2120 
2121 	assert(xborderpix == 0 || xborderpix == 1);
2122 
2123 	// palette (really RGB map) case
2124 	if (palette != nullptr)
2125 	{
2126 		if (xborderpix)
2127 		{
2128 			rgb_t srcpix = *src;
2129 			*dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
2130 		}
2131 		for (x = 0; x < width; x++)
2132 		{
2133 			rgb_t srcpix = *src++;
2134 			uint32_t dstval = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
2135 			for (int x2 = 0; x2 < xprescale; x2++)
2136 				*dst++ = dstval;
2137 		}
2138 		if (xborderpix)
2139 		{
2140 			rgb_t srcpix = *--src;
2141 			*dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
2142 		}
2143 	}
2144 
2145 	// direct case
2146 	else
2147 	{
2148 		if (xborderpix)
2149 			*dst++ = 0xff000000 | *src;
2150 		for (x = 0; x < width; x++)
2151 		{
2152 			rgb_t srcpix = *src++;
2153 			uint32_t dstval = 0xff000000 | srcpix;
2154 			for (int x2 = 0; x2 < xprescale; x2++)
2155 				*dst++ = dstval;
2156 		}
2157 		if (xborderpix)
2158 			*dst++ = 0xff000000 | *--src;
2159 	}
2160 }
2161 
2162 //============================================================
2163 //  copyline_argb32
2164 //============================================================
2165 
copyline_argb32(uint32_t * dst,const uint32_t * src,int width,const rgb_t * palette,int xborderpix,int xprescale)2166 static inline void copyline_argb32(uint32_t *dst, const uint32_t *src, int width, const rgb_t *palette, int xborderpix, int xprescale)
2167 {
2168 	int x;
2169 
2170 	assert(xborderpix == 0 || xborderpix == 1);
2171 
2172 	// palette (really RGB map) case
2173 	if (palette != nullptr)
2174 	{
2175 		if (xborderpix)
2176 		{
2177 			rgb_t srcpix = *src;
2178 			*dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
2179 		}
2180 		for (x = 0; x < width; x++)
2181 		{
2182 			rgb_t srcpix = *src++;
2183 			uint32_t dstval = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
2184 			for (int x2 = 0; x2 < xprescale; x2++)
2185 				*dst++ = dstval;
2186 		}
2187 		if (xborderpix)
2188 		{
2189 			rgb_t srcpix = *--src;
2190 			*dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
2191 		}
2192 	}
2193 
2194 	// direct case
2195 	else
2196 	{
2197 		if (xborderpix)
2198 			*dst++ = *src;
2199 		for (x = 0; x < width; x++)
2200 		{
2201 			rgb_t srcpix = *src++;
2202 			for (int x2 = 0; x2 < xprescale; x2++)
2203 				*dst++ = srcpix;
2204 		}
2205 		if (xborderpix)
2206 			*dst++ = *--src;
2207 	}
2208 }
2209 
ycc_to_rgb(uint8_t y,uint8_t cb,uint8_t cr)2210 static inline uint32_t ycc_to_rgb(uint8_t y, uint8_t cb, uint8_t cr)
2211 {
2212 	/* original equations:
2213 
2214 	    C = Y - 16
2215 	    D = Cb - 128
2216 	    E = Cr - 128
2217 
2218 	    R = clip(( 298 * C           + 409 * E + 128) >> 8)
2219 	    G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
2220 	    B = clip(( 298 * C + 516 * D           + 128) >> 8)
2221 
2222 	    R = clip(( 298 * (Y - 16)                    + 409 * (Cr - 128) + 128) >> 8)
2223 	    G = clip(( 298 * (Y - 16) - 100 * (Cb - 128) - 208 * (Cr - 128) + 128) >> 8)
2224 	    B = clip(( 298 * (Y - 16) + 516 * (Cb - 128)                    + 128) >> 8)
2225 
2226 	    R = clip(( 298 * Y - 298 * 16                        + 409 * Cr - 409 * 128 + 128) >> 8)
2227 	    G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8)
2228 	    B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128                        + 128) >> 8)
2229 
2230 	    R = clip(( 298 * Y - 298 * 16                        + 409 * Cr - 409 * 128 + 128) >> 8)
2231 	    G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8)
2232 	    B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128                        + 128) >> 8)
2233 	*/
2234 	int r, g, b, common;
2235 
2236 	common = 298 * y - 298 * 16;
2237 	r = (common +                        409 * cr - 409 * 128 + 128) >> 8;
2238 	g = (common - 100 * cb + 100 * 128 - 208 * cr + 208 * 128 + 128) >> 8;
2239 	b = (common + 516 * cb - 516 * 128                        + 128) >> 8;
2240 
2241 	if (r < 0) r = 0;
2242 	else if (r > 255) r = 255;
2243 	if (g < 0) g = 0;
2244 	else if (g > 255) g = 255;
2245 	if (b < 0) b = 0;
2246 	else if (b > 255) b = 255;
2247 
2248 	return rgb_t(0xff, r, g, b);
2249 }
2250 
2251 //============================================================
2252 //  copyline_yuy16_to_argb
2253 //============================================================
2254 
copyline_yuy16_to_argb(uint32_t * dst,const uint16_t * src,int width,const rgb_t * palette,int xborderpix,int xprescale)2255 static inline void copyline_yuy16_to_argb(uint32_t *dst, const uint16_t *src, int width, const rgb_t *palette, int xborderpix, int xprescale)
2256 {
2257 	int x;
2258 
2259 	assert(xborderpix == 0 || xborderpix == 2);
2260 	assert(width % 2 == 0);
2261 
2262 	// palette (really RGB map) case
2263 	if (palette != nullptr)
2264 	{
2265 		if (xborderpix)
2266 		{
2267 			uint16_t srcpix0 = src[0];
2268 			uint16_t srcpix1 = src[1];
2269 			uint8_t cb = srcpix0 & 0xff;
2270 			uint8_t cr = srcpix1 & 0xff;
2271 			*dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr);
2272 			*dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr);
2273 		}
2274 		for (x = 0; x < width / 2; x++)
2275 		{
2276 			uint16_t srcpix0 = *src++;
2277 			uint16_t srcpix1 = *src++;
2278 			uint8_t cb = srcpix0 & 0xff;
2279 			uint8_t cr = srcpix1 & 0xff;
2280 			uint32_t dstval0 = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr);
2281 			uint32_t dstval1 = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr);
2282 			for (int x2 = 0; x2 < xprescale; x2++)
2283 				*dst++ = dstval0;
2284 			for (int x2 = 0; x2 < xprescale; x2++)
2285 				*dst++ = dstval1;
2286 		}
2287 		if (xborderpix)
2288 		{
2289 			uint16_t srcpix1 = *--src;
2290 			uint16_t srcpix0 = *--src;
2291 			uint8_t cb = srcpix0 & 0xff;
2292 			uint8_t cr = srcpix1 & 0xff;
2293 			*dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr);
2294 			*dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr);
2295 		}
2296 	}
2297 
2298 	// direct case
2299 	else
2300 	{
2301 		if (xborderpix)
2302 		{
2303 			uint16_t srcpix0 = src[0];
2304 			uint16_t srcpix1 = src[1];
2305 			uint8_t cb = srcpix0 & 0xff;
2306 			uint8_t cr = srcpix1 & 0xff;
2307 			*dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr);
2308 			*dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr);
2309 		}
2310 		for (x = 0; x < width; x += 2)
2311 		{
2312 			uint16_t srcpix0 = *src++;
2313 			uint16_t srcpix1 = *src++;
2314 			uint8_t cb = srcpix0 & 0xff;
2315 			uint8_t cr = srcpix1 & 0xff;
2316 			uint32_t dstval0 = ycc_to_rgb(srcpix0 >> 8, cb, cr);
2317 			uint32_t dstval1 = ycc_to_rgb(srcpix1 >> 8, cb, cr);
2318 			for (int x2 = 0; x2 < xprescale; x2++)
2319 				*dst++ = dstval0;
2320 			for (int x2 = 0; x2 < xprescale; x2++)
2321 				*dst++ = dstval1;
2322 		}
2323 		if (xborderpix)
2324 		{
2325 			uint16_t srcpix1 = *--src;
2326 			uint16_t srcpix0 = *--src;
2327 			uint8_t cb = srcpix0 & 0xff;
2328 			uint8_t cr = srcpix1 & 0xff;
2329 			*dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr);
2330 			*dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr);
2331 		}
2332 	}
2333 }
2334 
2335 //============================================================
2336 //  texture_set_data
2337 //============================================================
2338 
texture_set_data(ogl_texture_info * texture,const render_texinfo * texsource,uint32_t flags)2339 static void texture_set_data(ogl_texture_info *texture, const render_texinfo *texsource, uint32_t flags)
2340 {
2341 	if ( texture->type == TEXTURE_TYPE_DYNAMIC )
2342 	{
2343 		assert(texture->pbo);
2344 		assert(!texture->nocopy);
2345 
2346 		texture->data = (uint32_t *) pfn_glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
2347 	}
2348 
2349 	// note that nocopy and borderpix are mutually exclusive, IOW
2350 	// they cannot be both true, thus this cannot lead to the
2351 	// borderpix code below writing to texsource->base .
2352 	if (texture->nocopy)
2353 	{
2354 		texture->data = (uint32_t *) texsource->base;
2355 	}
2356 
2357 	// always fill non-wrapping textures with an extra pixel on the top
2358 	if (texture->borderpix)
2359 	{
2360 		memset(texture->data, 0,
2361 				(texsource->width * texture->xprescale + 2) * sizeof(uint32_t));
2362 	}
2363 
2364 	// when necessary copy (and convert) the data
2365 	if (!texture->nocopy)
2366 	{
2367 		int y, y2;
2368 		uint8_t *dst;
2369 
2370 		for (y = 0; y < texsource->height; y++)
2371 		{
2372 			for (y2 = 0; y2 < texture->yprescale; y2++)
2373 			{
2374 				dst = (uint8_t *)(texture->data + (y * texture->yprescale + texture->borderpix + y2) * texture->rawwidth);
2375 
2376 				switch (PRIMFLAG_GET_TEXFORMAT(flags))
2377 				{
2378 					case TEXFORMAT_PALETTE16:
2379 						copyline_palette16((uint32_t *)dst, (uint16_t *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale);
2380 						break;
2381 
2382 					case TEXFORMAT_RGB32:
2383 						copyline_rgb32((uint32_t *)dst, (uint32_t *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale);
2384 						break;
2385 
2386 					case TEXFORMAT_ARGB32:
2387 						copyline_argb32((uint32_t *)dst, (uint32_t *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale);
2388 						break;
2389 
2390 					case TEXFORMAT_YUY16:
2391 						copyline_yuy16_to_argb((uint32_t *)dst, (uint16_t *)texsource->base + y * texsource->rowpixels, texsource->width, texsource->palette, texture->borderpix, texture->xprescale);
2392 						break;
2393 
2394 					default:
2395 						osd_printf_error("Unknown texture blendmode=%d format=%d\n", PRIMFLAG_GET_BLENDMODE(flags), PRIMFLAG_GET_TEXFORMAT(flags));
2396 						break;
2397 				}
2398 			}
2399 		}
2400 	}
2401 
2402 	// always fill non-wrapping textures with an extra pixel on the bottom
2403 	if (texture->borderpix)
2404 	{
2405 		memset((uint8_t *)texture->data +
2406 				(texsource->height + 1) * texture->rawwidth * sizeof(uint32_t),
2407 				0,
2408 			(texsource->width * texture->xprescale + 2) * sizeof(uint32_t));
2409 	}
2410 
2411 	if ( texture->type == TEXTURE_TYPE_SHADER )
2412 	{
2413 		pfn_glActiveTexture(GL_TEXTURE0);
2414 		glBindTexture(texture->texTarget, texture->texture);
2415 
2416 		if (texture->nocopy)
2417 			glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->texinfo.rowpixels);
2418 		else
2419 			glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth);
2420 
2421 		// and upload the image
2422 		glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight,
2423 				GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, texture->data);
2424 	}
2425 	else if ( texture->type == TEXTURE_TYPE_DYNAMIC )
2426 	{
2427 		glBindTexture(texture->texTarget, texture->texture);
2428 
2429 		glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth);
2430 
2431 		// unmap the buffer from the CPU space so it can DMA
2432 		pfn_glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
2433 
2434 		// kick off the DMA
2435 		glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight,
2436 					GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
2437 	}
2438 	else
2439 	{
2440 		glBindTexture(texture->texTarget, texture->texture);
2441 
2442 		// give the card a hint
2443 		if (texture->nocopy)
2444 			glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->texinfo.rowpixels);
2445 		else
2446 			glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->rawwidth);
2447 
2448 		// and upload the image
2449 		glTexSubImage2D(texture->texTarget, 0, 0, 0, texture->rawwidth, texture->rawheight,
2450 						GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, texture->data);
2451 	}
2452 }
2453 
2454 //============================================================
2455 //  texture_find
2456 //============================================================
2457 
compare_texture_primitive(const ogl_texture_info * texture,const render_primitive * prim)2458 static int compare_texture_primitive(const ogl_texture_info *texture, const render_primitive *prim)
2459 {
2460 	if (texture->texinfo.base == prim->texture.base &&
2461 		texture->texinfo.width == prim->texture.width &&
2462 		texture->texinfo.height == prim->texture.height &&
2463 		texture->texinfo.rowpixels == prim->texture.rowpixels &&
2464 		texture->texinfo.palette == prim->texture.palette &&
2465 		((texture->flags ^ prim->flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0)
2466 		return 1;
2467 	else
2468 		return 0;
2469 }
2470 
texture_find(const render_primitive * prim)2471 ogl_texture_info *renderer_ogl::texture_find(const render_primitive *prim)
2472 {
2473 	HashT texhash = texture_compute_hash(&prim->texture, prim->flags);
2474 	ogl_texture_info *texture;
2475 
2476 	texture = m_texhash[texhash];
2477 	if (texture != nullptr)
2478 	{
2479 		int i;
2480 		if (compare_texture_primitive(texture, prim))
2481 			return texture;
2482 		for (i=HASH_SIZE; i<HASH_SIZE + OVERFLOW_SIZE; i++)
2483 		{
2484 			texture = m_texhash[i];
2485 			if (texture != nullptr && compare_texture_primitive(texture, prim))
2486 				return texture;
2487 		}
2488 	}
2489 	return nullptr;
2490 }
2491 
2492 //============================================================
2493 //  texture_update
2494 //============================================================
2495 
texture_coord_update(ogl_texture_info * texture,const render_primitive * prim,int shaderIdx)2496 void renderer_ogl::texture_coord_update(ogl_texture_info *texture, const render_primitive *prim, int shaderIdx)
2497 {
2498 	float ustart = 0.0f, ustop = 0.0f;            // beginning/ending U coordinates
2499 	float vstart = 0.0f, vstop = 0.0f;            // beginning/ending V coordinates
2500 	float du, dv;
2501 
2502 	if ( texture->type != TEXTURE_TYPE_SHADER ||
2503 			( texture->type == TEXTURE_TYPE_SHADER && shaderIdx<=m_glsl_program_mb2sc ) )
2504 	{
2505 		// compute the U/V scale factors
2506 		if (texture->borderpix)
2507 		{
2508 			int unscaledwidth = (texture->rawwidth_create-2) / texture->xprescale + 2;
2509 			int unscaledheight = (texture->rawheight_create-2) / texture->yprescale + 2;
2510 			ustart = 1.0f / (float)(unscaledwidth);
2511 			ustop = (float)(prim->texture.width + 1) / (float)(unscaledwidth);
2512 			vstart = 1.0f / (float)(unscaledheight);
2513 			vstop = (float)(prim->texture.height + 1) / (float)(unscaledheight);
2514 		}
2515 		else
2516 		{
2517 			ustop  = (float)(prim->texture.width*texture->xprescale) / (float)texture->rawwidth_create;
2518 			vstop  = (float)(prim->texture.height*texture->yprescale) / (float)texture->rawheight_create;
2519 		}
2520 	}
2521 	else if ( texture->type == TEXTURE_TYPE_SHADER && shaderIdx>m_glsl_program_mb2sc )
2522 	{
2523 		int surf_w_pow2  = get_valid_pow2_value (m_width, texture->texpow2);
2524 		int surf_h_pow2  = get_valid_pow2_value (m_height, texture->texpow2);
2525 
2526 		ustop  = (float)(m_width) / (float)surf_w_pow2;
2527 		vstop  = (float)(m_height) / (float)surf_h_pow2;
2528 
2529 	}
2530 	else
2531 	{
2532 		assert(0); // ??
2533 	}
2534 
2535 	du = ustop - ustart;
2536 	dv = vstop - vstart;
2537 
2538 	if ( texture->texTarget == GL_TEXTURE_RECTANGLE_ARB )
2539 	{
2540 		// texture coordinates for TEXTURE_RECTANGLE are 0,0 -> w,h
2541 		// rather than 0,0 -> 1,1 as with normal OpenGL texturing
2542 		du *= (float)texture->rawwidth;
2543 		dv *= (float)texture->rawheight;
2544 	}
2545 
2546 	if ( texture->type == TEXTURE_TYPE_SHADER && shaderIdx!=m_glsl_program_mb2sc )
2547 	{
2548 		// 1:1 tex coord CCW (0/0) (1/0) (1/1) (0/1)
2549 		// we must go CW here due to the mame bitmap order
2550 		texture->texCoord[0]=ustart + du * 0.0f;
2551 		texture->texCoord[1]=vstart + dv * 1.0f;
2552 		texture->texCoord[2]=ustart + du * 1.0f;
2553 		texture->texCoord[3]=vstart + dv * 1.0f;
2554 		texture->texCoord[4]=ustart + du * 1.0f;
2555 		texture->texCoord[5]=vstart + dv * 0.0f;
2556 		texture->texCoord[6]=ustart + du * 0.0f;
2557 		texture->texCoord[7]=vstart + dv * 0.0f;
2558 	}
2559 	else
2560 	{
2561 		// transformation: mamebm -> scrn
2562 		texture->texCoord[0]=ustart + du * prim->texcoords.tl.u;
2563 		texture->texCoord[1]=vstart + dv * prim->texcoords.tl.v;
2564 		texture->texCoord[2]=ustart + du * prim->texcoords.tr.u;
2565 		texture->texCoord[3]=vstart + dv * prim->texcoords.tr.v;
2566 		texture->texCoord[4]=ustart + du * prim->texcoords.br.u;
2567 		texture->texCoord[5]=vstart + dv * prim->texcoords.br.v;
2568 		texture->texCoord[6]=ustart + du * prim->texcoords.bl.u;
2569 		texture->texCoord[7]=vstart + dv * prim->texcoords.bl.v;
2570 	}
2571 }
2572 
texture_mpass_flip(ogl_texture_info * texture,int shaderIdx)2573 void renderer_ogl::texture_mpass_flip(ogl_texture_info *texture, int shaderIdx)
2574 {
2575 	uint32_t mpass_src_idx = texture->mpass_dest_idx;
2576 
2577 	texture->mpass_dest_idx = (mpass_src_idx+1) % 2;
2578 
2579 	if ( shaderIdx>0 )
2580 	{
2581 		int uniform_location;
2582 		uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "mpass_texture");
2583 		pfn_glUniform1iARB(uniform_location, texture->mpass_textureunit[mpass_src_idx]-GL_TEXTURE0);
2584 		GL_CHECK_ERROR_NORMAL();
2585 	}
2586 
2587 	pfn_glActiveTexture(texture->mpass_textureunit[mpass_src_idx]);
2588 	if ( shaderIdx<=m_glsl_program_mb2sc )
2589 	{
2590 		glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[mpass_src_idx]);
2591 	}
2592 	else
2593 	{
2594 		glBindTexture(texture->texTarget, texture->mpass_texture_scrn[mpass_src_idx]);
2595 	}
2596 	pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]);
2597 	glBindTexture(texture->texTarget, 0);
2598 
2599 	pfn_glActiveTexture(texture->mpass_textureunit[texture->mpass_dest_idx]);
2600 
2601 	if ( shaderIdx<m_glsl_program_num-1 )
2602 	{
2603 		if ( shaderIdx>=m_glsl_program_mb2sc )
2604 		{
2605 			glBindTexture(texture->texTarget, texture->mpass_texture_scrn[texture->mpass_dest_idx]);
2606 			pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_scrn[texture->mpass_dest_idx]);
2607 		}
2608 		else
2609 		{
2610 			glBindTexture(texture->texTarget, texture->mpass_texture_mamebm[texture->mpass_dest_idx]);
2611 			pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, texture->mpass_fbo_mamebm[texture->mpass_dest_idx]);
2612 		}
2613 
2614 		if ( shaderIdx==0 )
2615 		{
2616 			glPushAttrib(GL_VIEWPORT_BIT);
2617 			GL_CHECK_ERROR_NORMAL();
2618 			glViewport(0.0, 0.0, (GLsizei)texture->rawwidth, (GLsizei)texture->rawheight);
2619 		}
2620 
2621 		if ( shaderIdx==m_glsl_program_mb2sc )
2622 		{
2623 			assert ( m_glsl_program_mb2sc < m_glsl_program_num-1 );
2624 			glPopAttrib(); // glViewport(0.0, 0.0, (GLsizei)window().width, (GLsizei)window().height)
2625 			GL_CHECK_ERROR_NORMAL();
2626 		}
2627 		glClear(GL_COLOR_BUFFER_BIT); // make sure the whole texture is redrawn ..
2628 	}
2629 	else
2630 	{
2631 		glBindTexture(texture->texTarget, 0);
2632 		pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
2633 
2634 		if ( m_glsl_program_mb2sc == m_glsl_program_num-1 )
2635 		{
2636 			glPopAttrib(); // glViewport(0.0, 0.0, (GLsizei)window().width, (GLsizei)window().height)
2637 			GL_CHECK_ERROR_NORMAL();
2638 		}
2639 
2640 		pfn_glActiveTexture(GL_TEXTURE0);
2641 		glBindTexture(texture->texTarget, 0);
2642 	}
2643 }
2644 
texture_shader_update(ogl_texture_info * texture,render_container * container,int shaderIdx)2645 void renderer_ogl::texture_shader_update(ogl_texture_info *texture, render_container *container, int shaderIdx)
2646 {
2647 	int uniform_location;
2648 	GLfloat vid_attributes[4];
2649 
2650 	if (container!=nullptr)
2651 	{
2652 		render_container::user_settings settings;
2653 		container->get_user_settings(settings);
2654 		/* FIXME: the code below is in just for illustration issue on
2655 		 * how to set shader variables. gamma, contrast and brightness are
2656 		 * handled already by the core
2657 		 */
2658 		vid_attributes[0] = settings.m_gamma;
2659 		vid_attributes[1] = settings.m_contrast;
2660 		vid_attributes[2] = settings.m_brightness;
2661 		vid_attributes[3] = 0.0f;
2662 		uniform_location = pfn_glGetUniformLocationARB(m_glsl_program[shaderIdx], "vid_attributes");
2663 		pfn_glUniform4fvARB(uniform_location, 1, &(vid_attributes[shaderIdx]));
2664 		if ( GL_CHECK_ERROR_QUIET() ) {
2665 			osd_printf_verbose("GLSL: could not set 'vid_attributes' for shader prog idx %d\n", shaderIdx);
2666 		}
2667 	}
2668 }
2669 
texture_update(const render_primitive * prim,int shaderIdx)2670 ogl_texture_info * renderer_ogl::texture_update(const render_primitive *prim, int shaderIdx)
2671 {
2672 	ogl_texture_info *texture = texture_find(prim);
2673 	int texBound = 0;
2674 
2675 	// if we didn't find one, create a new texture
2676 	if (texture == nullptr && prim->texture.base != nullptr)
2677 	{
2678 		texture = texture_create(&prim->texture, prim->flags);
2679 	}
2680 	else if (texture != nullptr)
2681 	{
2682 		if ( texture->type == TEXTURE_TYPE_SHADER )
2683 		{
2684 			pfn_glUseProgramObjectARB(m_glsl_program[shaderIdx]); // back to our shader
2685 		}
2686 		else if ( texture->type == TEXTURE_TYPE_DYNAMIC )
2687 		{
2688 			assert ( m_usepbo ) ;
2689 			pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, texture->pbo);
2690 			glEnable(texture->texTarget);
2691 		}
2692 		else
2693 		{
2694 			glEnable(texture->texTarget);
2695 		}
2696 	}
2697 
2698 	if (texture != nullptr)
2699 	{
2700 		if ( texture->type == TEXTURE_TYPE_SHADER )
2701 		{
2702 			texture_shader_update(texture, prim->container, shaderIdx);
2703 			if ( m_glsl_program_num>1 )
2704 			{
2705 				texture_mpass_flip(texture, shaderIdx);
2706 			}
2707 		}
2708 
2709 		if ( shaderIdx==0 ) // redundant for subsequent multipass shader
2710 		{
2711 			if (prim->texture.base != nullptr && texture->texinfo.seqid != prim->texture.seqid)
2712 			{
2713 				texture->texinfo.seqid = prim->texture.seqid;
2714 
2715 				// if we found it, but with a different seqid, copy the data
2716 				texture_set_data(texture, &prim->texture, prim->flags);
2717 				texBound=1;
2718 			}
2719 		}
2720 
2721 		if (!texBound) {
2722 			glBindTexture(texture->texTarget, texture->texture);
2723 		}
2724 		texture_coord_update(texture, prim, shaderIdx);
2725 
2726 		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2727 		if(m_usevbo)
2728 		{
2729 			pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, texture->texCoordBufferName );
2730 			// Load The Data
2731 			pfn_glBufferSubData( GL_ARRAY_BUFFER_ARB, 0, 4*2*sizeof(GLfloat), texture->texCoord );
2732 			glTexCoordPointer( 2, GL_FLOAT, 0, (char *) nullptr ); // we are using ARB VBO buffers
2733 		}
2734 		else
2735 		{
2736 			glTexCoordPointer(2, GL_FLOAT, 0, texture->texCoord);
2737 		}
2738 	}
2739 
2740 		return texture;
2741 }
2742 
texture_disable(ogl_texture_info * texture)2743 void renderer_ogl::texture_disable(ogl_texture_info * texture)
2744 {
2745 	if ( texture->type == TEXTURE_TYPE_SHADER )
2746 	{
2747 		assert ( m_useglsl );
2748 		pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
2749 	} else if ( texture->type == TEXTURE_TYPE_DYNAMIC )
2750 	{
2751 		pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0);
2752 		glDisable(texture->texTarget);
2753 	} else {
2754 		glDisable(texture->texTarget);
2755 	}
2756 }
2757 
texture_all_disable()2758 void renderer_ogl::texture_all_disable()
2759 {
2760 	if ( m_useglsl )
2761 	{
2762 		pfn_glUseProgramObjectARB(0); // back to fixed function pipeline
2763 
2764 		pfn_glActiveTexture(GL_TEXTURE3);
2765 		glBindTexture(GL_TEXTURE_2D, 0);
2766 		if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
2767 		pfn_glActiveTexture(GL_TEXTURE2);
2768 		glBindTexture(GL_TEXTURE_2D, 0);
2769 		if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
2770 		pfn_glActiveTexture(GL_TEXTURE1);
2771 		glBindTexture(GL_TEXTURE_2D, 0);
2772 		if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
2773 		pfn_glActiveTexture(GL_TEXTURE0);
2774 		glBindTexture(GL_TEXTURE_2D, 0);
2775 		if ( m_usefbo ) pfn_glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
2776 	}
2777 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
2778 
2779 	if(m_usetexturerect)
2780 	{
2781 		glDisable(GL_TEXTURE_RECTANGLE_ARB);
2782 	}
2783 	glDisable(GL_TEXTURE_2D);
2784 
2785 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2786 	if(m_usevbo)
2787 	{
2788 		pfn_glBindBuffer( GL_ARRAY_BUFFER_ARB, 0); // unbind ..
2789 	}
2790 	if ( m_usepbo )
2791 	{
2792 		pfn_glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0);
2793 	}
2794 }
2795