filename | src/drivers/video_gdk.c |
changeset | 635:76c63aac3590 |
next | 636:2ccf94f966fc |
author | nkeynes |
date | Thu Feb 14 13:54:11 2008 +0000 (15 years ago) |
branch | lxdream-render |
permissions | -rw-r--r-- |
last change | Commit render work in progress. Main changes: * Preliminary OSMesa support * Move the generic gl code out to pvr2/ * Implement scene data structure + reader * Remove the 1/z adjustments |
file | annotate | diff | log | raw |
nkeynes@635 | 1 | /** |
nkeynes@635 | 2 | * $Id: video_gtk.c 636 2008-01-30 11:31:21Z nkeynes $ |
nkeynes@635 | 3 | * |
nkeynes@635 | 4 | * The PC side of the video support (responsible for actually displaying / |
nkeynes@635 | 5 | * rendering frames) |
nkeynes@635 | 6 | * |
nkeynes@635 | 7 | * Copyright (c) 2005 Nathan Keynes. |
nkeynes@635 | 8 | * |
nkeynes@635 | 9 | * This program is free software; you can redistribute it and/or modify |
nkeynes@635 | 10 | * it under the terms of the GNU General Public License as published by |
nkeynes@635 | 11 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@635 | 12 | * (at your option) any later version. |
nkeynes@635 | 13 | * |
nkeynes@635 | 14 | * This program is distributed in the hope that it will be useful, |
nkeynes@635 | 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@635 | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@635 | 17 | * GNU General Public License for more details. |
nkeynes@635 | 18 | */ |
nkeynes@635 | 19 | #include <assert.h> |
nkeynes@635 | 20 | #include <stdlib.h> |
nkeynes@635 | 21 | #include <gdk/gdk.h> |
nkeynes@635 | 22 | #include <gdk-pixbuf/gdk-pixbuf.h> |
nkeynes@635 | 23 | #include <gtk/gtkwidget.h> |
nkeynes@635 | 24 | #include <GL/osmesa.h> |
nkeynes@635 | 25 | #include "lxdream.h" |
nkeynes@635 | 26 | #include "display.h" |
nkeynes@635 | 27 | |
nkeynes@635 | 28 | #define MAX_PIXBUF 16 |
nkeynes@635 | 29 | |
nkeynes@635 | 30 | extern GtkWidget *gtk_video_win; |
nkeynes@635 | 31 | extern int video_width, video_height; |
nkeynes@635 | 32 | |
nkeynes@635 | 33 | static render_buffer_t gdk_pixbuf_create_render_buffer( uint32_t width, uint32_t height ); |
nkeynes@635 | 34 | static void gdk_pixbuf_destroy_render_buffer( render_buffer_t buffer ); |
nkeynes@635 | 35 | static gboolean gdk_pixbuf_set_render_target( render_buffer_t buffer ); |
nkeynes@635 | 36 | static gboolean gdk_pixbuf_display_render_buffer( render_buffer_t buffer ); |
nkeynes@635 | 37 | static void gdk_pixbuf_load_frame_buffer( frame_buffer_t frame, render_buffer_t buffer ); |
nkeynes@635 | 38 | static gboolean gdk_pixbuf_display_blank( uint32_t colour ); |
nkeynes@635 | 39 | static gboolean gdk_pixbuf_read_render_buffer( unsigned char *target, render_buffer_t buffer, int rowstride, int format ); |
nkeynes@635 | 40 | |
nkeynes@635 | 41 | static void *pixbuf_array[MAX_PIXBUF]; |
nkeynes@635 | 42 | unsigned int pixbuf_max = 0; |
nkeynes@635 | 43 | OSMesaContext osmesa_context = NULL; |
nkeynes@635 | 44 | |
nkeynes@635 | 45 | void video_gdk_init_driver( display_driver_t driver ) |
nkeynes@635 | 46 | { |
nkeynes@635 | 47 | pixbuf_max = 0; |
nkeynes@635 | 48 | driver->create_render_buffer = gdk_pixbuf_create_render_buffer; |
nkeynes@635 | 49 | driver->destroy_render_buffer = gdk_pixbuf_destroy_render_buffer; |
nkeynes@635 | 50 | driver->set_render_target = gdk_pixbuf_set_render_target; |
nkeynes@635 | 51 | driver->display_render_buffer = gdk_pixbuf_display_render_buffer; |
nkeynes@635 | 52 | driver->load_frame_buffer = gdk_pixbuf_load_frame_buffer; |
nkeynes@635 | 53 | driver->display_blank = gdk_pixbuf_display_blank; |
nkeynes@635 | 54 | driver->read_render_buffer = gdk_pixbuf_read_render_buffer; |
nkeynes@635 | 55 | |
nkeynes@635 | 56 | osmesa_context = OSMesaCreateContextExt( OSMESA_RGBA, 32, 0, 0, 0 ); |
nkeynes@635 | 57 | OSMesaMakeCurrent( osmesa_context, NULL, GL_UNSIGNED_BYTE, 640, 480 ); |
nkeynes@635 | 58 | texcache_gl_init(); |
nkeynes@635 | 59 | } |
nkeynes@635 | 60 | |
nkeynes@635 | 61 | int video_gdk_find_free() |
nkeynes@635 | 62 | { |
nkeynes@635 | 63 | unsigned int i; |
nkeynes@635 | 64 | for( i=0; i<pixbuf_max; i++ ) { |
nkeynes@635 | 65 | if( pixbuf_array[i] == NULL ) { |
nkeynes@635 | 66 | return i; |
nkeynes@635 | 67 | } |
nkeynes@635 | 68 | } |
nkeynes@635 | 69 | if( i < MAX_PIXBUF ) { |
nkeynes@635 | 70 | return pixbuf_max++; |
nkeynes@635 | 71 | } |
nkeynes@635 | 72 | return -1; |
nkeynes@635 | 73 | } |
nkeynes@635 | 74 | |
nkeynes@635 | 75 | void video_gdk_shutdown() |
nkeynes@635 | 76 | { |
nkeynes@635 | 77 | unsigned int i; |
nkeynes@635 | 78 | for( i=0; i<pixbuf_max; i++ ) { |
nkeynes@635 | 79 | if( pixbuf_array[i] != NULL ) { |
nkeynes@635 | 80 | g_free(pixbuf_array[i]); |
nkeynes@635 | 81 | pixbuf_array[i] = NULL; |
nkeynes@635 | 82 | } |
nkeynes@635 | 83 | } |
nkeynes@635 | 84 | pixbuf_max = 0; |
nkeynes@635 | 85 | OSMesaDestroyContext( osmesa_context ); |
nkeynes@635 | 86 | } |
nkeynes@635 | 87 | |
nkeynes@635 | 88 | |
nkeynes@635 | 89 | static render_buffer_t gdk_pixbuf_create_render_buffer( uint32_t width, uint32_t height ) |
nkeynes@635 | 90 | { |
nkeynes@635 | 91 | render_buffer_t buf = g_malloc0(sizeof(struct render_buffer)); |
nkeynes@635 | 92 | gboolean alpha = FALSE; |
nkeynes@635 | 93 | buf->width = width; |
nkeynes@635 | 94 | buf->height = height; |
nkeynes@635 | 95 | buf->buf_id = video_gdk_find_free(); |
nkeynes@635 | 96 | pixbuf_array[buf->buf_id] = g_malloc0( width * height * 4 ); |
nkeynes@635 | 97 | return buf; |
nkeynes@635 | 98 | } |
nkeynes@635 | 99 | |
nkeynes@635 | 100 | static void gdk_pixbuf_destroy_render_buffer( render_buffer_t buffer ) |
nkeynes@635 | 101 | { |
nkeynes@635 | 102 | g_free(pixbuf_array[buffer->buf_id] ); |
nkeynes@635 | 103 | pixbuf_array[buffer->buf_id] = NULL; |
nkeynes@635 | 104 | if( buffer->buf_id == (pixbuf_max-1) ) { |
nkeynes@635 | 105 | pixbuf_max--; |
nkeynes@635 | 106 | } |
nkeynes@635 | 107 | } |
nkeynes@635 | 108 | |
nkeynes@635 | 109 | static gboolean gdk_pixbuf_display_render_buffer( render_buffer_t buffer ) |
nkeynes@635 | 110 | { |
nkeynes@635 | 111 | glFinish(); |
nkeynes@635 | 112 | |
nkeynes@635 | 113 | void *pb = pixbuf_array[buffer->buf_id]; |
nkeynes@635 | 114 | GdkGC *gc = gtk_video_win->style->fg_gc[GTK_STATE_NORMAL]; |
nkeynes@635 | 115 | GdkColor black = {0,0,0,0}; |
nkeynes@635 | 116 | |
nkeynes@635 | 117 | assert(gc); |
nkeynes@635 | 118 | |
nkeynes@635 | 119 | int x1=0,y1=0,x2=video_width,y2=video_height; |
nkeynes@635 | 120 | |
nkeynes@635 | 121 | int ah = video_width * 0.75; |
nkeynes@635 | 122 | |
nkeynes@635 | 123 | |
nkeynes@635 | 124 | if( ah > video_height ) { |
nkeynes@635 | 125 | int w = (video_height/0.75); |
nkeynes@635 | 126 | x1 = (video_width - w)/2; |
nkeynes@635 | 127 | x2 -= x1; |
nkeynes@635 | 128 | gdk_gc_set_foreground( gc, &black ); |
nkeynes@635 | 129 | gdk_gc_set_background( gc, &black ); |
nkeynes@635 | 130 | gdk_draw_rectangle( gtk_video_win->window, gc, TRUE, 0, 0, x1, video_height ); |
nkeynes@635 | 131 | gdk_draw_rectangle( gtk_video_win->window, gc, TRUE, x2, 0, video_width, video_height ); |
nkeynes@635 | 132 | } else if( ah < video_height ) { |
nkeynes@635 | 133 | y1 = (video_height - ah)/2; |
nkeynes@635 | 134 | y2 -= y1; |
nkeynes@635 | 135 | gdk_gc_set_foreground( gc, &black ); |
nkeynes@635 | 136 | gdk_gc_set_background( gc, &black ); |
nkeynes@635 | 137 | gdk_draw_rectangle( gtk_video_win->window, gc, TRUE, 0, 0, video_width, y1 ); |
nkeynes@635 | 138 | gdk_draw_rectangle( gtk_video_win->window, gc, TRUE, 0, y2, video_width, video_height ); |
nkeynes@635 | 139 | } |
nkeynes@635 | 140 | int w = x2-x1; |
nkeynes@635 | 141 | int h = y2-y1; |
nkeynes@635 | 142 | |
nkeynes@635 | 143 | if( w != buffer->width || h != buffer->height ) { |
nkeynes@635 | 144 | gdk_draw_rgb_32_image( gtk_video_win->window, gc, x1, y1, buffer->width, buffer->height, GDK_RGB_DITHER_NONE, |
nkeynes@635 | 145 | pb, buffer->width*4 ); |
nkeynes@635 | 146 | } else { |
nkeynes@635 | 147 | gdk_draw_rgb_32_image( gtk_video_win->window, gc, x1, y1, buffer->width, buffer->height, GDK_RGB_DITHER_NONE, |
nkeynes@635 | 148 | pb, buffer->width*4 ); |
nkeynes@635 | 149 | } |
nkeynes@635 | 150 | } |
nkeynes@635 | 151 | |
nkeynes@635 | 152 | static gboolean gdk_pixbuf_display_blank( uint32_t colour ) |
nkeynes@635 | 153 | { |
nkeynes@635 | 154 | GdkGC *gc = gtk_video_win->style->fg_gc[GTK_STATE_NORMAL]; |
nkeynes@635 | 155 | GdkColor col = { }; |
nkeynes@635 | 156 | |
nkeynes@635 | 157 | gdk_gc_set_foreground( gc, &col ); |
nkeynes@635 | 158 | gdk_gc_set_background( gc, &col ); |
nkeynes@635 | 159 | gdk_draw_rectangle( gtk_video_win->window, gc, TRUE, 0, 0, video_width, video_height ); |
nkeynes@635 | 160 | return TRUE; |
nkeynes@635 | 161 | } |
nkeynes@635 | 162 | |
nkeynes@635 | 163 | static gboolean gdk_pixbuf_set_render_target( render_buffer_t buffer ) |
nkeynes@635 | 164 | { |
nkeynes@635 | 165 | glFinish(); |
nkeynes@635 | 166 | void *pb = pixbuf_array[buffer->buf_id]; |
nkeynes@635 | 167 | OSMesaMakeCurrent( osmesa_context, pb, GL_UNSIGNED_BYTE, |
nkeynes@635 | 168 | buffer->width, buffer->height ); |
nkeynes@635 | 169 | //OSMesaPixelStore( OSMESA_Y_UP, 0 ); |
nkeynes@635 | 170 | glViewport( 0, 0, buffer->width, buffer->height ); |
nkeynes@635 | 171 | glDrawBuffer(GL_FRONT); |
nkeynes@635 | 172 | return TRUE; |
nkeynes@635 | 173 | } |
nkeynes@635 | 174 | |
nkeynes@635 | 175 | static void gdk_pixbuf_load_frame_buffer( frame_buffer_t frame, render_buffer_t buffer ) |
nkeynes@635 | 176 | { |
nkeynes@635 | 177 | glFinish(); |
nkeynes@635 | 178 | void *pb = pixbuf_array[buffer->buf_id]; |
nkeynes@635 | 179 | OSMesaMakeCurrent( osmesa_context, pb, GL_UNSIGNED_BYTE, |
nkeynes@635 | 180 | buffer->width, buffer->height ); |
nkeynes@635 | 181 | GLenum type = colour_formats[frame->colour_format].type; |
nkeynes@635 | 182 | GLenum format = colour_formats[frame->colour_format].format; |
nkeynes@635 | 183 | int bpp = colour_formats[frame->colour_format].bpp; |
nkeynes@635 | 184 | int rowstride = (frame->rowstride / bpp) - frame->width; |
nkeynes@635 | 185 | |
nkeynes@635 | 186 | gl_reset_state(); |
nkeynes@635 | 187 | glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride ); |
nkeynes@635 | 188 | glRasterPos2f(0.375, frame->height-0.375); |
nkeynes@635 | 189 | glPixelZoom( 1.0, 1.0 ); |
nkeynes@635 | 190 | glDrawPixels( frame->width, frame->height, format, type, frame->data ); |
nkeynes@635 | 191 | glFlush(); |
nkeynes@635 | 192 | } |
nkeynes@635 | 193 | |
nkeynes@635 | 194 | static gboolean gdk_pixbuf_read_render_buffer( unsigned char *target, render_buffer_t buffer, int rowstride, int format ) |
nkeynes@635 | 195 | { |
nkeynes@635 | 196 | glFinish(); |
nkeynes@635 | 197 | void *pb = pixbuf_array[buffer->buf_id]; |
nkeynes@635 | 198 | OSMesaMakeCurrent( osmesa_context, pb, GL_UNSIGNED_BYTE, |
nkeynes@635 | 199 | buffer->width, buffer->height ); |
nkeynes@635 | 200 | glReadBuffer( GL_FRONT ); |
nkeynes@635 | 201 | return gl_read_render_buffer( target, buffer, rowstride, format ); |
nkeynes@635 | 202 | |
nkeynes@635 | 203 | } |
.