nkeynes@635: /** nkeynes@636: * $Id$ nkeynes@635: * nkeynes@635: * The PC side of the video support (responsible for actually displaying / nkeynes@635: * rendering frames) nkeynes@635: * nkeynes@635: * Copyright (c) 2005 Nathan Keynes. nkeynes@635: * nkeynes@635: * This program is free software; you can redistribute it and/or modify nkeynes@635: * it under the terms of the GNU General Public License as published by nkeynes@635: * the Free Software Foundation; either version 2 of the License, or nkeynes@635: * (at your option) any later version. nkeynes@635: * nkeynes@635: * This program is distributed in the hope that it will be useful, nkeynes@635: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@635: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@635: * GNU General Public License for more details. nkeynes@635: */ nkeynes@635: #include nkeynes@635: #include nkeynes@635: #include nkeynes@635: #include nkeynes@635: #include nkeynes@661: #include nkeynes@635: #include nkeynes@635: #include "lxdream.h" nkeynes@635: #include "display.h" nkeynes@635: nkeynes@635: #define MAX_PIXBUF 16 nkeynes@635: nkeynes@661: extern GtkWidget *gtk_video_drawable; nkeynes@635: extern int video_width, video_height; nkeynes@635: nkeynes@635: static render_buffer_t gdk_pixbuf_create_render_buffer( uint32_t width, uint32_t height ); nkeynes@635: static void gdk_pixbuf_destroy_render_buffer( render_buffer_t buffer ); nkeynes@635: static gboolean gdk_pixbuf_set_render_target( render_buffer_t buffer ); nkeynes@669: static void gdk_pixbuf_display_render_buffer( render_buffer_t buffer ); nkeynes@635: static void gdk_pixbuf_load_frame_buffer( frame_buffer_t frame, render_buffer_t buffer ); nkeynes@669: static void gdk_pixbuf_display_blank( uint32_t colour ); nkeynes@635: static gboolean gdk_pixbuf_read_render_buffer( unsigned char *target, render_buffer_t buffer, int rowstride, int format ); nkeynes@635: nkeynes@635: static void *pixbuf_array[MAX_PIXBUF]; nkeynes@635: unsigned int pixbuf_max = 0; nkeynes@635: OSMesaContext osmesa_context = NULL; nkeynes@635: nkeynes@635: void video_gdk_init_driver( display_driver_t driver ) nkeynes@635: { nkeynes@635: pixbuf_max = 0; nkeynes@635: driver->create_render_buffer = gdk_pixbuf_create_render_buffer; nkeynes@635: driver->destroy_render_buffer = gdk_pixbuf_destroy_render_buffer; nkeynes@635: driver->set_render_target = gdk_pixbuf_set_render_target; nkeynes@635: driver->display_render_buffer = gdk_pixbuf_display_render_buffer; nkeynes@635: driver->load_frame_buffer = gdk_pixbuf_load_frame_buffer; nkeynes@635: driver->display_blank = gdk_pixbuf_display_blank; nkeynes@635: driver->read_render_buffer = gdk_pixbuf_read_render_buffer; nkeynes@635: nkeynes@635: osmesa_context = OSMesaCreateContextExt( OSMESA_RGBA, 32, 0, 0, 0 ); nkeynes@635: OSMesaMakeCurrent( osmesa_context, NULL, GL_UNSIGNED_BYTE, 640, 480 ); nkeynes@639: pvr2_setup_gl_context(); nkeynes@635: } nkeynes@635: nkeynes@635: int video_gdk_find_free() nkeynes@635: { nkeynes@635: unsigned int i; nkeynes@635: for( i=0; iwidth = width; nkeynes@635: buf->height = height; nkeynes@635: buf->buf_id = video_gdk_find_free(); nkeynes@635: pixbuf_array[buf->buf_id] = g_malloc0( width * height * 4 ); nkeynes@635: return buf; nkeynes@635: } nkeynes@635: nkeynes@635: static void gdk_pixbuf_destroy_render_buffer( render_buffer_t buffer ) nkeynes@635: { nkeynes@635: g_free(pixbuf_array[buffer->buf_id] ); nkeynes@635: pixbuf_array[buffer->buf_id] = NULL; nkeynes@635: if( buffer->buf_id == (pixbuf_max-1) ) { nkeynes@736: pixbuf_max--; nkeynes@635: } nkeynes@635: } nkeynes@635: nkeynes@669: static void gdk_pixbuf_display_render_buffer( render_buffer_t buffer ) nkeynes@635: { nkeynes@635: glFinish(); nkeynes@635: nkeynes@635: void *pb = pixbuf_array[buffer->buf_id]; nkeynes@661: GdkGC *gc = gtk_video_drawable->style->fg_gc[GTK_STATE_NORMAL]; nkeynes@635: GdkColor black = {0,0,0,0}; nkeynes@635: nkeynes@635: assert(gc); nkeynes@635: nkeynes@635: int x1=0,y1=0,x2=video_width,y2=video_height; nkeynes@635: nkeynes@635: int ah = video_width * 0.75; nkeynes@635: nkeynes@635: nkeynes@635: if( ah > video_height ) { nkeynes@736: int w = (video_height/0.75); nkeynes@736: x1 = (video_width - w)/2; nkeynes@736: x2 -= x1; nkeynes@736: gdk_gc_set_foreground( gc, &black ); nkeynes@736: gdk_gc_set_background( gc, &black ); nkeynes@736: gdk_draw_rectangle( gtk_video_drawable->window, gc, TRUE, 0, 0, x1, video_height ); nkeynes@736: gdk_draw_rectangle( gtk_video_drawable->window, gc, TRUE, x2, 0, video_width, video_height ); nkeynes@635: } else if( ah < video_height ) { nkeynes@736: y1 = (video_height - ah)/2; nkeynes@736: y2 -= y1; nkeynes@736: gdk_gc_set_foreground( gc, &black ); nkeynes@736: gdk_gc_set_background( gc, &black ); nkeynes@736: gdk_draw_rectangle( gtk_video_drawable->window, gc, TRUE, 0, 0, video_width, y1 ); nkeynes@736: gdk_draw_rectangle( gtk_video_drawable->window, gc, TRUE, 0, y2, video_width, video_height ); nkeynes@635: } nkeynes@635: int w = x2-x1; nkeynes@635: int h = y2-y1; nkeynes@736: nkeynes@635: if( w != buffer->width || h != buffer->height ) { nkeynes@736: gdk_draw_rgb_32_image( gtk_video_drawable->window, gc, x1, y1, buffer->width, buffer->height, GDK_RGB_DITHER_NONE, nkeynes@736: pb, buffer->width*4 ); nkeynes@635: } else { nkeynes@736: gdk_draw_rgb_32_image( gtk_video_drawable->window, gc, x1, y1, buffer->width, buffer->height, GDK_RGB_DITHER_NONE, nkeynes@736: pb, buffer->width*4 ); nkeynes@635: } nkeynes@635: } nkeynes@635: nkeynes@669: static void gdk_pixbuf_display_blank( uint32_t colour ) nkeynes@635: { nkeynes@661: GdkGC *gc = gtk_video_drawable->style->fg_gc[GTK_STATE_NORMAL]; nkeynes@635: GdkColor col = { }; nkeynes@635: nkeynes@635: gdk_gc_set_foreground( gc, &col ); nkeynes@635: gdk_gc_set_background( gc, &col ); nkeynes@661: gdk_draw_rectangle( gtk_video_drawable->window, gc, TRUE, 0, 0, video_width, video_height ); nkeynes@635: } nkeynes@635: nkeynes@635: static gboolean gdk_pixbuf_set_render_target( render_buffer_t buffer ) nkeynes@635: { nkeynes@635: glFinish(); nkeynes@635: void *pb = pixbuf_array[buffer->buf_id]; nkeynes@635: OSMesaMakeCurrent( osmesa_context, pb, GL_UNSIGNED_BYTE, nkeynes@736: buffer->width, buffer->height ); nkeynes@635: //OSMesaPixelStore( OSMESA_Y_UP, 0 ); nkeynes@635: glViewport( 0, 0, buffer->width, buffer->height ); nkeynes@635: glDrawBuffer(GL_FRONT); nkeynes@635: return TRUE; nkeynes@635: } nkeynes@635: nkeynes@635: static void gdk_pixbuf_load_frame_buffer( frame_buffer_t frame, render_buffer_t buffer ) nkeynes@635: { nkeynes@635: glFinish(); nkeynes@635: void *pb = pixbuf_array[buffer->buf_id]; nkeynes@635: OSMesaMakeCurrent( osmesa_context, pb, GL_UNSIGNED_BYTE, nkeynes@736: buffer->width, buffer->height ); nkeynes@635: GLenum type = colour_formats[frame->colour_format].type; nkeynes@635: GLenum format = colour_formats[frame->colour_format].format; nkeynes@635: int bpp = colour_formats[frame->colour_format].bpp; nkeynes@635: int rowstride = (frame->rowstride / bpp) - frame->width; nkeynes@736: nkeynes@635: gl_reset_state(); nkeynes@635: glPixelStorei( GL_UNPACK_ROW_LENGTH, rowstride ); nkeynes@635: glRasterPos2f(0.375, frame->height-0.375); nkeynes@635: glPixelZoom( 1.0, 1.0 ); nkeynes@635: glDrawPixels( frame->width, frame->height, format, type, frame->data ); nkeynes@635: glFlush(); nkeynes@635: } nkeynes@635: nkeynes@635: static gboolean gdk_pixbuf_read_render_buffer( unsigned char *target, render_buffer_t buffer, int rowstride, int format ) nkeynes@635: { nkeynes@635: glFinish(); nkeynes@635: void *pb = pixbuf_array[buffer->buf_id]; nkeynes@635: OSMesaMakeCurrent( osmesa_context, pb, GL_UNSIGNED_BYTE, nkeynes@736: buffer->width, buffer->height ); nkeynes@635: glReadBuffer( GL_FRONT ); nkeynes@635: return gl_read_render_buffer( target, buffer, rowstride, format ); nkeynes@635: nkeynes@635: }