Search
lxdream.org :: lxdream/src/drivers/video_gl.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/video_gl.c
changeset 1299:645ccec8dfb0
prev1298:d0eb2307b847
author nkeynes
date Sun May 24 19:46:06 2015 +1000 (8 years ago)
permissions -rw-r--r--
last change Remove static from gl_load_frame_buffer() - also needed by video_egl.c
Fix error location in gl_frame_buffer_to_tex
file annotate diff log raw
nkeynes@635
     1
/**
nkeynes@635
     2
 * $Id$
nkeynes@635
     3
 *
nkeynes@635
     4
 * Common GL code that doesn't depend on a specific implementation
nkeynes@635
     5
 *
nkeynes@635
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@635
     7
 *
nkeynes@635
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@635
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@635
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@635
    11
 * (at your option) any later version.
nkeynes@635
    12
 *
nkeynes@635
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@635
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@635
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@635
    16
 * GNU General Public License for more details.
nkeynes@635
    17
 */
nkeynes@635
    18
nkeynes@1282
    19
#include <assert.h>
nkeynes@635
    20
#include <sys/time.h>
nkeynes@635
    21
nkeynes@635
    22
#include "display.h"
nkeynes@635
    23
#include "pvr2/pvr2.h"
nkeynes@1236
    24
#include "pvr2/glutil.h"
nkeynes@1240
    25
#include "pvr2/shaders.h"
nkeynes@635
    26
#include "drivers/video_gl.h"
nkeynes@635
    27
nkeynes@1236
    28
uint32_t video_width, video_height;
nkeynes@1236
    29
struct video_vertex {
nkeynes@1236
    30
    float x,y;
nkeynes@1236
    31
    float u,v;
nkeynes@1240
    32
    float r,g,b,a;
nkeynes@1236
    33
};
nkeynes@1236
    34
nkeynes@1236
    35
static struct video_box_t {
nkeynes@1236
    36
    float viewMatrix[16];
nkeynes@1236
    37
    struct video_vertex gap1[4];
nkeynes@1236
    38
    struct video_vertex gap2[4];
nkeynes@1236
    39
    struct video_vertex video_view[4];
nkeynes@1236
    40
    struct video_vertex invert_view[4];
nkeynes@1236
    41
} video_box;
nkeynes@1236
    42
nkeynes@1251
    43
void gl_set_video_size( uint32_t width, uint32_t height, int flipped )
nkeynes@1236
    44
{
nkeynes@1236
    45
    video_width = width;
nkeynes@1236
    46
    video_height = height;
nkeynes@1236
    47
nkeynes@1236
    48
    int x1=0,y1=0,x2=video_width,y2=video_height;
nkeynes@1251
    49
    int top = 0, bottom = 1;
nkeynes@1251
    50
nkeynes@1251
    51
    if( flipped ) {
nkeynes@1251
    52
        top = 1;
nkeynes@1251
    53
        bottom = 0;
nkeynes@1251
    54
    }
nkeynes@1236
    55
nkeynes@1236
    56
    int ah = video_width * 0.75;
nkeynes@1236
    57
nkeynes@1236
    58
    if( ah > video_height ) {
nkeynes@1236
    59
        int w = (video_height/0.75);
nkeynes@1236
    60
        x1 = (video_width - w)/2;
nkeynes@1236
    61
        x2 -= x1;
nkeynes@1236
    62
        video_box.gap1[0].x = 0; video_box.gap1[0].y = 0;
nkeynes@1236
    63
        video_box.gap1[1].x = x1; video_box.gap1[1].y = 0;
nkeynes@1262
    64
        video_box.gap1[2].x = x1; video_box.gap1[2].y = video_height;
nkeynes@1259
    65
        video_box.gap1[3].x = 0; video_box.gap1[3].y = video_height;
nkeynes@1236
    66
        video_box.gap2[0].x = x2; video_box.gap2[0].y = 0;
nkeynes@1236
    67
        video_box.gap2[1].x = video_width; video_box.gap2[1].y = 0;
nkeynes@1259
    68
        video_box.gap2[2].x = video_width; video_box.gap2[2].y = video_height;
nkeynes@1259
    69
        video_box.gap2[3].x = x2; video_box.gap2[3].y = video_height;
nkeynes@1236
    70
    } else if( ah < video_height ) {
nkeynes@1236
    71
        y1 = (video_height - ah)/2;
nkeynes@1236
    72
        y2 -= y1;
nkeynes@1236
    73
nkeynes@1236
    74
        video_box.gap1[0].x = 0; video_box.gap1[0].y = 0;
nkeynes@1236
    75
        video_box.gap1[1].x = video_width; video_box.gap1[1].y = 0;
nkeynes@1259
    76
        video_box.gap1[2].x = video_width; video_box.gap1[2].y = y1;
nkeynes@1259
    77
        video_box.gap1[3].x = 0; video_box.gap1[3].y = y1;
nkeynes@1236
    78
        video_box.gap2[0].x = 0; video_box.gap2[0].y = y2;
nkeynes@1236
    79
        video_box.gap2[1].x = video_width; video_box.gap2[1].y = y2;
nkeynes@1259
    80
        video_box.gap2[2].x = video_width; video_box.gap2[2].y = video_height;
nkeynes@1259
    81
        video_box.gap2[3].x = 0; video_box.gap2[3].y = video_height;
nkeynes@1236
    82
    }
nkeynes@1236
    83
nkeynes@1236
    84
    video_box.video_view[0].x = x1; video_box.video_view[0].y = y1;
nkeynes@1259
    85
    video_box.video_view[0].u = 0; video_box.video_view[0].v = top;
nkeynes@1236
    86
    video_box.video_view[1].x = x2; video_box.video_view[1].y = y1;
nkeynes@1259
    87
    video_box.video_view[1].u = 1; video_box.video_view[1].v = top;
nkeynes@1259
    88
    video_box.video_view[2].x = x2; video_box.video_view[2].y = y2;
nkeynes@1259
    89
    video_box.video_view[2].u = 1; video_box.video_view[2].v = bottom;
nkeynes@1259
    90
    video_box.video_view[3].x = x1; video_box.video_view[3].y = y2;
nkeynes@1259
    91
    video_box.video_view[3].u = 0; video_box.video_view[3].v = bottom;
nkeynes@1236
    92
nkeynes@1236
    93
    memcpy( &video_box.invert_view, &video_box.video_view, sizeof(video_box.video_view) );
nkeynes@1251
    94
    video_box.invert_view[0].v = bottom; video_box.invert_view[1].v = bottom;
nkeynes@1251
    95
    video_box.invert_view[2].v = top; video_box.invert_view[3].v = top;
nkeynes@1236
    96
nkeynes@1236
    97
    defineOrthoMatrix(video_box.viewMatrix, video_width, video_height, 0, 65535);
nkeynes@1236
    98
}
nkeynes@635
    99
nkeynes@1239
   100
#ifdef HAVE_OPENGL_FIXEDFUNC
nkeynes@635
   101
/**
nkeynes@1236
   102
 * Setup the gl context for writes to the display output.
nkeynes@635
   103
 */
nkeynes@1246
   104
void gl_framebuffer_setup()
nkeynes@635
   105
{
nkeynes@1239
   106
    glViewport( 0, 0, video_width, video_height );
nkeynes@1236
   107
    glLoadMatrixf(video_box.viewMatrix);
nkeynes@1236
   108
    glBlendFunc( GL_ONE, GL_ZERO );
nkeynes@1236
   109
    glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
nkeynes@1236
   110
    glVertexPointer(2, GL_FLOAT, sizeof(struct video_vertex), &video_box.gap1[0].x);
nkeynes@1236
   111
    glColorPointer(3, GL_FLOAT, sizeof(struct video_vertex), &video_box.gap1[0].r);
nkeynes@1236
   112
    glTexCoordPointer(2, GL_FLOAT, sizeof(struct video_vertex), &video_box.gap1[0].u);
nkeynes@1236
   113
    glEnableClientState( GL_VERTEX_ARRAY );
nkeynes@1236
   114
    glEnableClientState( GL_COLOR_ARRAY );
nkeynes@1236
   115
    glEnableClientState( GL_TEXTURE_COORD_ARRAY );
nkeynes@635
   116
}
nkeynes@635
   117
nkeynes@1246
   118
void gl_framebuffer_cleanup()
nkeynes@1240
   119
{
nkeynes@1240
   120
    glDisableClientState( GL_VERTEX_ARRAY );
nkeynes@1240
   121
    glDisableClientState( GL_COLOR_ARRAY );
nkeynes@1240
   122
    glDisableClientState( GL_TEXTURE_COORD_ARRAY );
nkeynes@1240
   123
}
nkeynes@1239
   124
#else
nkeynes@1246
   125
void gl_framebuffer_setup()
nkeynes@1239
   126
{
nkeynes@1240
   127
    glViewport( 0, 0, video_width, video_height );
nkeynes@1240
   128
    glBlendFunc( GL_ONE, GL_ZERO );
nkeynes@1240
   129
    glsl_use_basic_shader();
nkeynes@1240
   130
    glsl_set_basic_shader_view_matrix(video_box.viewMatrix);
nkeynes@1240
   131
    glsl_set_basic_shader_in_vertex_pointer(&video_box.gap1[0].x, sizeof(struct video_vertex));
nkeynes@1240
   132
    glsl_set_basic_shader_in_colour_pointer(&video_box.gap1[0].r, sizeof(struct video_vertex));
nkeynes@1240
   133
    glsl_set_basic_shader_in_texcoord_pointer(&video_box.gap1[0].u, sizeof(struct video_vertex));
nkeynes@1240
   134
    glsl_set_basic_shader_primary_texture(0);
nkeynes@1240
   135
}
nkeynes@1240
   136
nkeynes@1246
   137
void gl_framebuffer_cleanup()
nkeynes@1240
   138
{
nkeynes@1240
   139
    glsl_clear_shader();
nkeynes@1239
   140
}
nkeynes@1239
   141
#endif
nkeynes@1239
   142
nkeynes@635
   143
void gl_display_render_buffer( render_buffer_t buffer )
nkeynes@635
   144
{
nkeynes@635
   145
    gl_texture_window( buffer->width, buffer->height, buffer->buf_id, buffer->inverted );
nkeynes@635
   146
}
nkeynes@635
   147
nkeynes@854
   148
/**
nkeynes@854
   149
 * Convert window coordinates to dreamcast device coords (640x480) using the 
nkeynes@854
   150
 * same viewable area as gl_texture_window.
nkeynes@854
   151
 * If the coordinates are outside the viewable area, the result is -1,-1.
nkeynes@854
   152
 */ 
nkeynes@854
   153
void gl_window_to_system_coords( int *x, int *y )
nkeynes@854
   154
{
nkeynes@854
   155
    int x1=0,y1=0,x2=video_width,y2=video_height;
nkeynes@854
   156
nkeynes@854
   157
    int ah = video_width * 0.75;
nkeynes@854
   158
nkeynes@854
   159
    if( ah > video_height ) {
nkeynes@854
   160
        int w = (video_height/0.75);
nkeynes@854
   161
        x1 = (video_width - w)/2;
nkeynes@854
   162
        x2 -= x1;
nkeynes@854
   163
    } else if( ah < video_height ) {
nkeynes@854
   164
        y1 = (video_height - ah)/2;
nkeynes@854
   165
        y2 -= y1;
nkeynes@854
   166
    }
nkeynes@854
   167
    if( *x < x1 || *x >= x2 || *y < y1 || *y >= y2 ) {
nkeynes@854
   168
        *x = -1;
nkeynes@854
   169
        *y = -1;
nkeynes@854
   170
    } else {
nkeynes@854
   171
        *x = (*x - x1) * DISPLAY_WIDTH / (x2-x1);
nkeynes@854
   172
        *y = (*y - y1) * DISPLAY_HEIGHT / (y2-y1);
nkeynes@854
   173
    }
nkeynes@854
   174
}
nkeynes@854
   175
nkeynes@1259
   176
/**
nkeynes@1259
   177
 * Use quads if we have them, otherwise tri-fans.
nkeynes@1259
   178
 */
nkeynes@1259
   179
#ifndef GL_QUADS
nkeynes@1260
   180
#define GL_QUADS GL_TRIANGLE_FAN
nkeynes@1259
   181
#endif
nkeynes@1259
   182
nkeynes@635
   183
void gl_texture_window( int width, int height, int tex_id, gboolean inverted )
nkeynes@635
   184
{
nkeynes@1240
   185
    /* Set video box tex alpha to 1 */
nkeynes@1240
   186
    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;
nkeynes@1251
   187
    video_box.invert_view[0].a = video_box.invert_view[1].a = video_box.invert_view[2].a = video_box.invert_view[3].a = 1;
nkeynes@1240
   188
nkeynes@635
   189
    /* Reset display parameters */
nkeynes@1236
   190
    gl_framebuffer_setup();
nkeynes@1259
   191
    glDrawArrays(GL_QUADS, 0, 4);
nkeynes@1259
   192
    glDrawArrays(GL_QUADS, 4, 4);
nkeynes@1236
   193
    glEnable(GL_TEXTURE_2D);
nkeynes@1236
   194
    glBindTexture(GL_TEXTURE_2D,tex_id);
nkeynes@1222
   195
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nkeynes@1222
   196
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nkeynes@1259
   197
    glDrawArrays(GL_QUADS, inverted ? 12 : 8, 4);
nkeynes@1236
   198
    glDisable(GL_TEXTURE_2D);
nkeynes@1251
   199
    gl_framebuffer_cleanup();
nkeynes@635
   200
    glFlush();
nkeynes@635
   201
}
nkeynes@635
   202
nkeynes@669
   203
void gl_display_blank( uint32_t colour )
nkeynes@635
   204
{
nkeynes@1236
   205
    /* Set the video_box background colour */
nkeynes@1236
   206
    video_box.video_view[0].r = ((float)(((colour >> 16) & 0xFF) + 1)) / 256.0;
nkeynes@1236
   207
    video_box.video_view[0].g = ((float)(((colour >> 8) & 0xFF) + 1)) / 256.0;
nkeynes@1236
   208
    video_box.video_view[0].b = ((float)((colour & 0xFF) + 1)) / 256.0;
nkeynes@1240
   209
    video_box.video_view[0].a = 0;
nkeynes@1236
   210
    memcpy( &video_box.video_view[1].r, &video_box.video_view[0].r, sizeof(float)*3 );
nkeynes@1236
   211
    memcpy( &video_box.video_view[2].r, &video_box.video_view[0].r, sizeof(float)*3 );
nkeynes@1236
   212
    memcpy( &video_box.video_view[3].r, &video_box.video_view[0].r, sizeof(float)*3 );
nkeynes@1236
   213
nkeynes@1236
   214
    /* And render */
nkeynes@1236
   215
    gl_framebuffer_setup();
nkeynes@1259
   216
    glDrawArrays(GL_QUADS, 0, 4);
nkeynes@1259
   217
    glDrawArrays(GL_QUADS, 4, 4);
nkeynes@1259
   218
    glDrawArrays(GL_QUADS, 8, 4);
nkeynes@1251
   219
    gl_framebuffer_cleanup();
nkeynes@635
   220
    glFlush();
nkeynes@635
   221
}
nkeynes@635
   222
nkeynes@1282
   223
nkeynes@1282
   224
#ifdef HAVE_GLES2
nkeynes@1282
   225
/* Note: OpenGL ES only officialy supports glReadPixels for the RGBA32 format
nkeynes@1282
   226
 * (and doesn't necessarily support glPixelStore(GL_PACK_ROW_LENGTH) either.
nkeynes@1282
   227
 * As a result, we end up needed to do the format conversion ourselves.
nkeynes@1282
   228
 */
nkeynes@1282
   229
nkeynes@1282
   230
/**
nkeynes@1282
   231
 * Swizzle 32-bit RGBA to specified target format, truncating components where
nkeynes@1282
   232
 * necessary. Target may == source.
nkeynes@1282
   233
 * @param target destination buffer
nkeynes@1282
   234
 * @param Source buffer, which must be in 8-bit-per-component RGBA format, fully packed.
nkeynes@1282
   235
 * @param width width of image in pixels
nkeynes@1282
   236
 * @param height height of image in pixels
nkeynes@1282
   237
 * @param target_stride Stride of target buffer, in bytes
nkeynes@1282
   238
 * @param colour_format
nkeynes@1282
   239
 */
nkeynes@1282
   240
static void rgba32_to_target( unsigned char *target, const uint32_t *source, int width, int height, int target_stride, int colour_format )
nkeynes@1282
   241
{
nkeynes@1282
   242
    int x,y;
nkeynes@1282
   243
nkeynes@1282
   244
    if( target_stride == 0 )
nkeynes@1282
   245
        target_stride = width * colour_formats[colour_format].bpp;
nkeynes@1282
   246
nkeynes@1282
   247
    switch( colour_format ) {
nkeynes@1282
   248
    case COLFMT_BGRA1555:
nkeynes@1282
   249
        for( y=0; y<height; y++ ) {
nkeynes@1282
   250
            uint16_t *d = (uint16_t *)target;
nkeynes@1282
   251
            for( x=0; x<width; x++ ) {
nkeynes@1282
   252
                uint32_t v = *source++;
nkeynes@1282
   253
                *d++ = (uint16_t)( ((v & 0x80000000) >> 16) | ((v & 0x00F80000) >> 19) |
nkeynes@1282
   254
                        ((v & 0x0000F800)>>6) | ((v & 0x000000F8) << 7) );
nkeynes@1282
   255
            }
nkeynes@1282
   256
            target += target_stride;
nkeynes@1282
   257
        }
nkeynes@1282
   258
        break;
nkeynes@1282
   259
    case COLFMT_RGB565:
nkeynes@1282
   260
        for( y=0; y<height; y++ ) {
nkeynes@1282
   261
            uint16_t *d = (uint16_t *)target;
nkeynes@1282
   262
            for( x=0; x<width; x++ ) {
nkeynes@1282
   263
                uint32_t v = *source++;
nkeynes@1282
   264
                *d++ = (uint16_t)( ((v & 0x00F80000) >> 19) | ((v & 0x0000FC00) >> 5) | ((v & 0x000000F8)<<8) );
nkeynes@1282
   265
            }
nkeynes@1282
   266
            target += target_stride;
nkeynes@1282
   267
        }
nkeynes@1282
   268
        break;
nkeynes@1282
   269
    case COLFMT_BGRA4444:
nkeynes@1282
   270
        for( y=0; y<height; y++ ) {
nkeynes@1282
   271
            uint16_t *d = (uint16_t *)target;
nkeynes@1282
   272
            for( x=0; x<width; x++ ) {
nkeynes@1282
   273
                uint32_t v = *source++;
nkeynes@1282
   274
                *d++ = (uint16_t)( ((v & 0xF0000000) >> 16) | ((v & 0x00F00000) >> 20) |
nkeynes@1282
   275
                        ((v & 0x0000F000) >> 8) | ((v & 0x000000F0)<<4) );
nkeynes@1282
   276
            }
nkeynes@1282
   277
            target += target_stride;
nkeynes@1282
   278
        }
nkeynes@1282
   279
        break;
nkeynes@1282
   280
    case COLFMT_BGRA8888:
nkeynes@1282
   281
        for( y=0; y<height; y++ ) {
nkeynes@1282
   282
            uint32_t *d = (uint32_t *)target;
nkeynes@1282
   283
            for( x=0; x<width; x++ ) {
nkeynes@1282
   284
                uint32_t v = *source++;
nkeynes@1282
   285
                *d++ = (v & 0xFF00FF00) | ((v & 0x00FF0000) >> 16) | ((v & 0x000000FF)<<16);
nkeynes@1282
   286
            }
nkeynes@1282
   287
            target += target_stride;
nkeynes@1282
   288
        }
nkeynes@1282
   289
        break;
nkeynes@1282
   290
    case COLFMT_BGR0888:
nkeynes@1282
   291
        for( y=0; y<height; y++ ) {
nkeynes@1282
   292
            uint32_t *d = (uint32_t *)target;
nkeynes@1282
   293
            for( x=0; x<width; x++ ) {
nkeynes@1282
   294
                uint32_t v = *source++;
nkeynes@1282
   295
                *d++ = ((v & 0x00FF0000) >> 16) | (v & 0x0000FF00) | ((v & 0x000000FF)<<16);
nkeynes@1282
   296
            }
nkeynes@1282
   297
            target += target_stride;
nkeynes@1282
   298
        }
nkeynes@1282
   299
        break;
nkeynes@1282
   300
    case COLFMT_BGR888:
nkeynes@1282
   301
        for( y=0; y<height; y++ ) {
nkeynes@1282
   302
            uint8_t *d = (uint8_t *)target;
nkeynes@1282
   303
            for( x=0; x<width; x++ ) {
nkeynes@1282
   304
                uint32_t v = *source++;
nkeynes@1282
   305
                *d++ = (uint8_t)(v >> 16);
nkeynes@1282
   306
                *d++ = (uint8_t)(v >> 8);
nkeynes@1282
   307
                *d++ = (uint8_t)(v);
nkeynes@1282
   308
            }
nkeynes@1282
   309
            target += target_stride;
nkeynes@1282
   310
        }
nkeynes@1282
   311
        break;
nkeynes@1282
   312
    case COLFMT_RGB888:
nkeynes@1282
   313
        for( y=0; y<height; y++ ) {
nkeynes@1282
   314
            uint8_t *d = (uint8_t *)target;
nkeynes@1282
   315
            for( x=0; x<width; x++ ) {
nkeynes@1282
   316
                uint32_t v = *source++;
nkeynes@1282
   317
                *d++ = (uint8_t)(v);
nkeynes@1282
   318
                *d++ = (uint8_t)(v >> 8);
nkeynes@1282
   319
                *d++ = (uint8_t)(v >> 16);
nkeynes@1282
   320
            }
nkeynes@1282
   321
            target += target_stride;
nkeynes@1282
   322
        }
nkeynes@1282
   323
        break;
nkeynes@1282
   324
    default:
nkeynes@1282
   325
        assert( 0 && "Unsupported colour format" );
nkeynes@1282
   326
    }
nkeynes@1282
   327
}
nkeynes@1282
   328
nkeynes@1282
   329
/**
nkeynes@1282
   330
 * Convert data into an acceptable form for loading into an RGBA texture.
nkeynes@1282
   331
 */
nkeynes@1282
   332
static int target_to_rgba(  uint32_t *target, const unsigned char *source, int width, int height, int source_stride, int colour_format )
nkeynes@1282
   333
{
nkeynes@1282
   334
    int x,y;
nkeynes@1282
   335
    uint16_t *d;
nkeynes@1282
   336
    switch( colour_format ) {
nkeynes@1282
   337
    case COLFMT_BGRA1555:
nkeynes@1282
   338
        d = (uint16_t *)target;
nkeynes@1282
   339
        for( y=0; y<height; y++ ) {
nkeynes@1282
   340
            uint16_t *s = (uint16_t *)source;
nkeynes@1282
   341
            for( x=0; x<width; x++ ) {
nkeynes@1282
   342
                uint16_t v = *s++;
nkeynes@1282
   343
                *d++ = (v >> 15) | (v<<1);
nkeynes@1282
   344
            }
nkeynes@1282
   345
            source += source_stride;
nkeynes@1282
   346
        }
nkeynes@1282
   347
        return GL_UNSIGNED_SHORT_5_5_5_1;
nkeynes@1282
   348
        break;
nkeynes@1282
   349
    case COLFMT_RGB565:
nkeynes@1282
   350
        /* Need to expand to RGBA32 in order to have room for an alpha component */
nkeynes@1282
   351
        for( y=0; y<height; y++ ) {
nkeynes@1282
   352
            uint16_t *s = (uint16_t *)source;
nkeynes@1282
   353
            for( x=0; x<width; x++ ) {
nkeynes@1282
   354
                uint32_t v = (uint32_t)*s++;
nkeynes@1282
   355
                *target++ = ((v & 0xF800)>>8) | ((v & 0x07E0) <<5) | ((v & 0x001F) << 19) |
nkeynes@1282
   356
                        ((v & 0xE000) >> 13) | ((v &0x0600) >> 1) | ((v & 0x001C) << 14);
nkeynes@1282
   357
            }
nkeynes@1282
   358
            source += source_stride;
nkeynes@1282
   359
        }
nkeynes@1282
   360
        return GL_UNSIGNED_BYTE;
nkeynes@1282
   361
    case COLFMT_BGRA4444:
nkeynes@1282
   362
        d = (uint16_t *)target;
nkeynes@1282
   363
        for( y=0; y<height; y++ ) {
nkeynes@1282
   364
            uint16_t *s = (uint16_t *)source;
nkeynes@1282
   365
            for( x=0; x<width; x++ ) {
nkeynes@1282
   366
                uint16_t v = *s++;
nkeynes@1282
   367
                *d++ = (v >> 12) | (v<<4);
nkeynes@1282
   368
            }
nkeynes@1282
   369
            source += source_stride;
nkeynes@1282
   370
        }
nkeynes@1282
   371
        return GL_UNSIGNED_SHORT_4_4_4_4;
nkeynes@1282
   372
    case COLFMT_RGB888:
nkeynes@1282
   373
        for( y=0; y<height; y++ ) {
nkeynes@1282
   374
            uint8_t *s = (uint8_t *)source;
nkeynes@1282
   375
            for( x=0; x<width; x++ ) {
nkeynes@1282
   376
                *target++ = s[0] | (s[1]<<8) | (s[2]<<16);
nkeynes@1282
   377
                s += 3;
nkeynes@1282
   378
            }
nkeynes@1282
   379
            source += source_stride;
nkeynes@1282
   380
        }
nkeynes@1282
   381
        return GL_UNSIGNED_BYTE;
nkeynes@1282
   382
    case COLFMT_BGRA8888:
nkeynes@1282
   383
        for( y=0; y<height; y++ ) {
nkeynes@1282
   384
            uint32_t *s = (uint32_t *)source;
nkeynes@1282
   385
            for( x=0; x<width; x++ ) {
nkeynes@1282
   386
                uint32_t v = (uint32_t)*s++;
nkeynes@1282
   387
                *target++ = (v & 0xFF00FF00) | ((v & 0x00FF0000) >> 16) | ((v & 0x000000FF) << 16);
nkeynes@1282
   388
            }
nkeynes@1282
   389
            source += source_stride;
nkeynes@1282
   390
        }
nkeynes@1282
   391
        return GL_UNSIGNED_BYTE;
nkeynes@1282
   392
    case COLFMT_BGR0888:
nkeynes@1282
   393
        for( y=0; y<height; y++ ) {
nkeynes@1282
   394
            uint32_t *s = (uint32_t *)source;
nkeynes@1282
   395
            for( x=0; x<width; x++ ) {
nkeynes@1282
   396
                uint32_t v = (uint32_t)*s++;
nkeynes@1282
   397
                *target++ = (v & 0x0000FF00) | ((v & 0x00FF0000) >> 16) | ((v & 0x000000FF) << 16);
nkeynes@1282
   398
            }
nkeynes@1282
   399
            source += source_stride;
nkeynes@1282
   400
        }
nkeynes@1282
   401
        return GL_UNSIGNED_BYTE;
nkeynes@1282
   402
    case COLFMT_BGR888:
nkeynes@1282
   403
        for( y=0; y<height; y++ ) {
nkeynes@1282
   404
            uint8_t *s = (uint8_t *)source;
nkeynes@1282
   405
            for( x=0; x<width; x++ ) {
nkeynes@1282
   406
                *target++ = s[2] | (s[1]<<8) | (s[0]<<16);
nkeynes@1282
   407
                s += 3;
nkeynes@1282
   408
            }
nkeynes@1282
   409
            source += source_stride;
nkeynes@1282
   410
        }
nkeynes@1282
   411
        return GL_UNSIGNED_BYTE;
nkeynes@1282
   412
    default:
nkeynes@1282
   413
        assert( 0 && "Unsupported colour format" );
nkeynes@1282
   414
    }
nkeynes@1282
   415
nkeynes@1282
   416
nkeynes@1282
   417
}
nkeynes@1282
   418
nkeynes@1282
   419
nkeynes@1282
   420
gboolean gl_read_render_buffer( unsigned char *target, render_buffer_t buffer,
nkeynes@1282
   421
        int rowstride, int colour_format )
nkeynes@1282
   422
{
nkeynes@1282
   423
    if( colour_formats[colour_format].bpp == 4 && (rowstride == 0 || rowstride == buffer->width*4) ) {
nkeynes@1282
   424
        glReadPixels( 0, 0, buffer->width, buffer->height, GL_RGBA, GL_UNSIGNED_BYTE, target );
nkeynes@1282
   425
        rgba32_to_target( target, (uint32_t *)target, buffer->width, buffer->height, rowstride, colour_format );
nkeynes@1282
   426
    } else {
nkeynes@1282
   427
        int size = buffer->width * buffer->height;
nkeynes@1282
   428
        uint32_t tmp[size];
nkeynes@1282
   429
nkeynes@1282
   430
        glReadPixels( 0, 0, buffer->width, buffer->height, GL_RGBA, GL_UNSIGNED_BYTE, tmp );
nkeynes@1282
   431
        rgba32_to_target( target, tmp, buffer->width, buffer->height, rowstride, colour_format );
nkeynes@1282
   432
    }
nkeynes@1282
   433
    return TRUE;
nkeynes@1282
   434
}
nkeynes@1282
   435
nkeynes@1298
   436
void gl_frame_buffer_to_tex( frame_buffer_t frame, int tex_id )
nkeynes@1282
   437
{
nkeynes@1282
   438
    int size = frame->width * frame->height;
nkeynes@1282
   439
    uint32_t tmp[size];
nkeynes@1282
   440
nkeynes@1282
   441
    GLenum type = target_to_rgba( tmp, frame->data, frame->width, frame->height, frame->rowstride, frame->colour_format );
nkeynes@1282
   442
    glBindTexture( GL_TEXTURE_2D, tex_id );
nkeynes@1282
   443
    glTexSubImage2D( GL_TEXTURE_2D, 0, 0,0, frame->width, frame->height, GL_RGBA, type, tmp );
nkeynes@1299
   444
    gl_check_error("gl_frame_buffer_to_tex:glTexSubImage2DBGRA");
nkeynes@1282
   445
}
nkeynes@1282
   446
nkeynes@1282
   447
#else
nkeynes@635
   448
/**
nkeynes@635
   449
 * Generic GL read_render_buffer. This function assumes that the caller
nkeynes@635
   450
 * has already set the appropriate glReadBuffer(); in other words, unless
nkeynes@635
   451
 * there's only one buffer this needs to be wrapped.
nkeynes@635
   452
 */
nkeynes@635
   453
gboolean gl_read_render_buffer( unsigned char *target, render_buffer_t buffer, 
nkeynes@736
   454
                                int rowstride, int colour_format ) 
nkeynes@635
   455
{
nkeynes@635
   456
    glFinish();
nkeynes@635
   457
    GLenum type = colour_formats[colour_format].type;
nkeynes@635
   458
    GLenum format = colour_formats[colour_format].format;
nkeynes@635
   459
    // int line_size = buffer->width * colour_formats[colour_format].bpp;
nkeynes@635
   460
    // int size = line_size * buffer->height;
nkeynes@635
   461
    int glrowstride = (rowstride / colour_formats[colour_format].bpp) - buffer->width;
nkeynes@635
   462
    glPixelStorei( GL_PACK_ROW_LENGTH, glrowstride );
nkeynes@635
   463
    glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
nkeynes@1236
   464
    glPixelStorei( GL_PACK_ROW_LENGTH, 0 );
nkeynes@635
   465
    return TRUE;
nkeynes@635
   466
}
nkeynes@1244
   467
nkeynes@1298
   468
void gl_frame_buffer_to_tex( frame_buffer_t frame, int tex_id )
nkeynes@1282
   469
{
nkeynes@1282
   470
    GLenum type = colour_formats[frame->colour_format].type;
nkeynes@1282
   471
    GLenum format = colour_formats[frame->colour_format].format;
nkeynes@1282
   472
    int bpp = colour_formats[frame->colour_format].bpp;
nkeynes@1282
   473
    int rowstride = (frame->rowstride / bpp) - frame->width;
nkeynes@1282
   474
nkeynes@1282
   475
    glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride );
nkeynes@1282
   476
    glBindTexture( GL_TEXTURE_2D, tex_id );
nkeynes@1282
   477
    glTexSubImage2DBGRA( 0, 0,0,
nkeynes@1282
   478
                     frame->width, frame->height, format, type, frame->data, FALSE );
nkeynes@1282
   479
    glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
nkeynes@1282
   480
}
nkeynes@1282
   481
#endif
nkeynes@1282
   482
nkeynes@1299
   483
void gl_load_frame_buffer( frame_buffer_t frame, render_buffer_t render )
nkeynes@1298
   484
{
nkeynes@1298
   485
    gl_frame_buffer_to_tex( frame, render->tex_id );
nkeynes@1298
   486
}
nkeynes@1298
   487
nkeynes@1282
   488
nkeynes@1258
   489
gboolean gl_init_driver( display_driver_t driver, gboolean need_fbo )
nkeynes@1258
   490
{
nkeynes@1258
   491
    /* Use framebuffer objects if available */
nkeynes@1258
   492
    if( gl_fbo_is_supported() ) {
nkeynes@1258
   493
        gl_fbo_init(driver);
nkeynes@1258
   494
    } else if( need_fbo ) {
nkeynes@1258
   495
        ERROR( "Framebuffer objects not supported - unable to construct an off-screen buffer" );
nkeynes@1258
   496
        return FALSE;
nkeynes@1258
   497
    }
nkeynes@1258
   498
nkeynes@1258
   499
    /* Use SL shaders if available */
nkeynes@1298
   500
    glsl_init(driver);
nkeynes@1258
   501
#ifndef HAVE_OPENGL_FIXEDFUNC
nkeynes@1298
   502
    if( !driver->has_sl ) { /* Shaders are required if we don't have fixed-functionality */
nkeynes@1258
   503
        gl_fbo_shutdown();
nkeynes@1258
   504
        return FALSE;
nkeynes@1258
   505
    }
nkeynes@1258
   506
#endif
nkeynes@1258
   507
nkeynes@1258
   508
    /* Use vertex arrays, VBOs, etc, if we have them */
nkeynes@1258
   509
    gl_vbo_init(driver);
nkeynes@1258
   510
nkeynes@1258
   511
    driver->capabilities.has_gl = TRUE;
nkeynes@1282
   512
    driver->capabilities.has_bgra = isGLBGRATextureSupported();
nkeynes@1258
   513
    return TRUE;
nkeynes@1258
   514
}
nkeynes@1258
   515
nkeynes@1244
   516
static gboolean video_gl_init();
nkeynes@1244
   517
nkeynes@1244
   518
/**
nkeynes@1244
   519
 * Minimal GL driver (assuming that the GL context is already set up externally)
nkeynes@1244
   520
 * This requires FBO support (since otherwise we have no way to get a render buffer)
nkeynes@1244
   521
 */
nkeynes@1244
   522
struct display_driver display_gl_driver = {
nkeynes@1244
   523
        "gl", N_("OpenGL driver"), video_gl_init, NULL,
nkeynes@1244
   524
        NULL, NULL, NULL,
nkeynes@1244
   525
        NULL, NULL, NULL, NULL,
nkeynes@1244
   526
        gl_load_frame_buffer, gl_display_render_buffer, gl_display_blank,
nkeynes@1244
   527
        NULL, gl_read_render_buffer, NULL, NULL
nkeynes@1244
   528
};
nkeynes@1244
   529
nkeynes@1244
   530
static gboolean video_gl_init()
nkeynes@1244
   531
{
nkeynes@1258
   532
    return gl_init_driver(&display_gl_driver, TRUE);
nkeynes@1244
   533
}
.