filename | src/drivers/video_gl.c |
changeset | 1244:6b54ef5ed413 |
prev | 1240:190df8a791ca |
next | 1246:887f7b0ac7f3 |
author | nkeynes |
date | Tue Feb 28 18:22:52 2012 +1000 (11 years ago) |
permissions | -rw-r--r-- |
last change | Add a GL-only video driver for android usage (since the Java code is responsible for creating the context) |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * Common GL code that doesn't depend on a specific implementation
5 *
6 * Copyright (c) 2005 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #include <sys/time.h>
21 #include "display.h"
22 #include "pvr2/pvr2.h"
23 #include "pvr2/glutil.h"
24 #include "pvr2/shaders.h"
25 #include "drivers/video_gl.h"
27 /* FIXME: Need to actually handle this case */
28 #ifndef GL_PACK_ROW_LENGTH
29 #define glPixelStorei(key,val)
30 #endif
32 uint32_t video_width, video_height;
33 struct video_vertex {
34 float x,y;
35 float u,v;
36 float r,g,b,a;
37 };
39 static struct video_box_t {
40 float viewMatrix[16];
41 struct video_vertex gap1[4];
42 struct video_vertex gap2[4];
43 struct video_vertex video_view[4];
44 struct video_vertex invert_view[4];
45 } video_box;
47 void gl_set_video_size( uint32_t width, uint32_t height )
48 {
49 video_width = width;
50 video_height = height;
52 int x1=0,y1=0,x2=video_width,y2=video_height;
54 int ah = video_width * 0.75;
56 if( ah > video_height ) {
57 int w = (video_height/0.75);
58 x1 = (video_width - w)/2;
59 x2 -= x1;
60 video_box.gap1[0].x = 0; video_box.gap1[0].y = 0;
61 video_box.gap1[1].x = x1; video_box.gap1[1].y = 0;
62 video_box.gap1[2].x = 0; video_box.gap1[2].y = video_height;
63 video_box.gap1[3].x = x2; video_box.gap1[3].y = video_height;
64 video_box.gap2[0].x = x2; video_box.gap2[0].y = 0;
65 video_box.gap2[1].x = video_width; video_box.gap2[1].y = 0;
66 video_box.gap2[2].x = x2; video_box.gap2[2].y = video_height;
67 video_box.gap2[3].x = video_width; video_box.gap2[3].y = video_height;
68 } else if( ah < video_height ) {
69 y1 = (video_height - ah)/2;
70 y2 -= y1;
72 video_box.gap1[0].x = 0; video_box.gap1[0].y = 0;
73 video_box.gap1[1].x = video_width; video_box.gap1[1].y = 0;
74 video_box.gap1[2].x = 0; video_box.gap1[2].y = y1;
75 video_box.gap1[3].x = video_width; video_box.gap1[3].y = y1;
76 video_box.gap2[0].x = 0; video_box.gap2[0].y = y2;
77 video_box.gap2[1].x = video_width; video_box.gap2[1].y = y2;
78 video_box.gap2[2].x = 0; video_box.gap2[2].y = video_height;
79 video_box.gap2[3].x = video_width; video_box.gap2[3].y = video_height;
80 }
82 video_box.video_view[0].x = x1; video_box.video_view[0].y = y1;
83 video_box.video_view[0].u = 0; video_box.video_view[0].v = 0;
84 video_box.video_view[1].x = x2; video_box.video_view[1].y = y1;
85 video_box.video_view[1].u = 1; video_box.video_view[1].v = 0;
86 video_box.video_view[2].x = x1; video_box.video_view[2].y = y2;
87 video_box.video_view[2].u = 0; video_box.video_view[2].v = 1;
88 video_box.video_view[3].x = x2; video_box.video_view[3].y = y2;
89 video_box.video_view[3].u = 1; video_box.video_view[3].v = 1;
91 memcpy( &video_box.invert_view, &video_box.video_view, sizeof(video_box.video_view) );
92 video_box.invert_view[0].v = 1; video_box.invert_view[1].v = 1;
93 video_box.invert_view[2].v = 0; video_box.invert_view[3].v = 0;
95 defineOrthoMatrix(video_box.viewMatrix, video_width, video_height, 0, 65535);
96 }
98 #ifdef HAVE_OPENGL_FIXEDFUNC
99 /**
100 * Setup the gl context for writes to the display output.
101 */
102 static void gl_framebuffer_setup()
103 {
104 glViewport( 0, 0, video_width, video_height );
105 glLoadMatrixf(video_box.viewMatrix);
106 glBlendFunc( GL_ONE, GL_ZERO );
107 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
108 glVertexPointer(2, GL_FLOAT, sizeof(struct video_vertex), &video_box.gap1[0].x);
109 glColorPointer(3, GL_FLOAT, sizeof(struct video_vertex), &video_box.gap1[0].r);
110 glTexCoordPointer(2, GL_FLOAT, sizeof(struct video_vertex), &video_box.gap1[0].u);
111 glEnableClientState( GL_VERTEX_ARRAY );
112 glEnableClientState( GL_COLOR_ARRAY );
113 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
114 }
116 static void gl_framebuffer_cleanup()
117 {
118 glDisableClientState( GL_VERTEX_ARRAY );
119 glDisableClientState( GL_COLOR_ARRAY );
120 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
121 }
122 #else
123 static void gl_framebuffer_setup()
124 {
125 glViewport( 0, 0, video_width, video_height );
126 glBlendFunc( GL_ONE, GL_ZERO );
127 glsl_use_basic_shader();
128 glsl_set_basic_shader_view_matrix(video_box.viewMatrix);
129 glsl_set_basic_shader_in_vertex_pointer(&video_box.gap1[0].x, sizeof(struct video_vertex));
130 glsl_set_basic_shader_in_colour_pointer(&video_box.gap1[0].r, sizeof(struct video_vertex));
131 glsl_set_basic_shader_in_texcoord_pointer(&video_box.gap1[0].u, sizeof(struct video_vertex));
132 glsl_set_basic_shader_primary_texture(0);
133 }
135 static void gl_framebuffer_cleanup()
136 {
137 glsl_clear_shader();
138 }
139 #endif
141 void gl_display_render_buffer( render_buffer_t buffer )
142 {
143 gl_texture_window( buffer->width, buffer->height, buffer->buf_id, buffer->inverted );
144 }
146 /**
147 * Convert window coordinates to dreamcast device coords (640x480) using the
148 * same viewable area as gl_texture_window.
149 * If the coordinates are outside the viewable area, the result is -1,-1.
150 */
151 void gl_window_to_system_coords( int *x, int *y )
152 {
153 int x1=0,y1=0,x2=video_width,y2=video_height;
155 int ah = video_width * 0.75;
157 if( ah > video_height ) {
158 int w = (video_height/0.75);
159 x1 = (video_width - w)/2;
160 x2 -= x1;
161 } else if( ah < video_height ) {
162 y1 = (video_height - ah)/2;
163 y2 -= y1;
164 }
165 if( *x < x1 || *x >= x2 || *y < y1 || *y >= y2 ) {
166 *x = -1;
167 *y = -1;
168 } else {
169 *x = (*x - x1) * DISPLAY_WIDTH / (x2-x1);
170 *y = (*y - y1) * DISPLAY_HEIGHT / (y2-y1);
171 }
172 }
174 void gl_texture_window( int width, int height, int tex_id, gboolean inverted )
175 {
176 /* Set video box tex alpha to 1 */
177 video_box.video_view[0].a = video_box.video_view[1].a = video_box.video_view[2].a = video_box.video_view[3].a = 1;
179 /* Reset display parameters */
180 gl_framebuffer_setup();
181 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
182 glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
183 glEnable(GL_TEXTURE_2D);
184 glBindTexture(GL_TEXTURE_2D,tex_id);
185 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
186 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
187 glDrawArrays(GL_TRIANGLE_STRIP, inverted ? 12 : 8, 4);
188 glDisable(GL_TEXTURE_2D);
189 glFlush();
190 gl_framebuffer_cleanup();
191 }
193 gboolean gl_load_frame_buffer( frame_buffer_t frame, int tex_id )
194 {
195 GLenum type = colour_formats[frame->colour_format].type;
196 GLenum format = colour_formats[frame->colour_format].format;
197 int bpp = colour_formats[frame->colour_format].bpp;
198 int rowstride = (frame->rowstride / bpp) - frame->width;
200 glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );
201 glBindTexture( GL_TEXTURE_2D, tex_id );
202 glTexSubImage2D( GL_TEXTURE_2D, 0, 0,0,
203 frame->width, frame->height, format, type, frame->data );
204 glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
205 return TRUE;
206 }
208 void gl_display_blank( uint32_t colour )
209 {
210 /* Set the video_box background colour */
211 video_box.video_view[0].r = ((float)(((colour >> 16) & 0xFF) + 1)) / 256.0;
212 video_box.video_view[0].g = ((float)(((colour >> 8) & 0xFF) + 1)) / 256.0;
213 video_box.video_view[0].b = ((float)((colour & 0xFF) + 1)) / 256.0;
214 video_box.video_view[0].a = 0;
215 memcpy( &video_box.video_view[1].r, &video_box.video_view[0].r, sizeof(float)*3 );
216 memcpy( &video_box.video_view[2].r, &video_box.video_view[0].r, sizeof(float)*3 );
217 memcpy( &video_box.video_view[3].r, &video_box.video_view[0].r, sizeof(float)*3 );
219 /* And render */
220 gl_framebuffer_setup();
221 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
222 glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
223 glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
224 glFlush();
225 gl_framebuffer_cleanup();
226 }
228 /**
229 * Generic GL read_render_buffer. This function assumes that the caller
230 * has already set the appropriate glReadBuffer(); in other words, unless
231 * there's only one buffer this needs to be wrapped.
232 */
233 gboolean gl_read_render_buffer( unsigned char *target, render_buffer_t buffer,
234 int rowstride, int colour_format )
235 {
236 glFinish();
237 GLenum type = colour_formats[colour_format].type;
238 GLenum format = colour_formats[colour_format].format;
239 // int line_size = buffer->width * colour_formats[colour_format].bpp;
240 // int size = line_size * buffer->height;
241 int glrowstride = (rowstride / colour_formats[colour_format].bpp) - buffer->width;
242 glPixelStorei( GL_PACK_ROW_LENGTH, glrowstride );
243 glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
244 glPixelStorei( GL_PACK_ROW_LENGTH, 0 );
245 return TRUE;
246 }
248 static gboolean video_gl_init();
250 /**
251 * Minimal GL driver (assuming that the GL context is already set up externally)
252 * This requires FBO support (since otherwise we have no way to get a render buffer)
253 */
254 struct display_driver display_gl_driver = {
255 "gl", N_("OpenGL driver"), video_gl_init, NULL,
256 NULL, NULL, NULL,
257 NULL, NULL, NULL, NULL,
258 gl_load_frame_buffer, gl_display_render_buffer, gl_display_blank,
259 NULL, gl_read_render_buffer, NULL, NULL
260 };
262 static gboolean video_gl_init()
263 {
264 if( gl_fbo_is_supported() ) {
265 display_gl_driver.capabilities.has_gl = TRUE;
266 gl_fbo_init(&display_gl_driver);
267 gl_vbo_init(&display_gl_driver);
268 return TRUE;
269 } else {
270 return FALSE;
271 }
272 }
.