00001
00009 #include <string.h>
00010
00011 #include "alleggl.h"
00012 #include "allglint.h"
00013 #include "glvtable.h"
00014
00015
00016
00017
00018 static unsigned long agl_write_line_c(BITMAP * bmp, int line);
00019 static void agl_unwrite_line_c(BITMAP * bmp);
00020
00021
00022
00023
00024
00025 #ifdef ALLEGRO_NO_ASM
00026
00027 static void *agl_write_line = agl_write_line_c;
00028 static void *agl_unwrite_line = agl_unwrite_line_c;
00029 #else
00030
00031 #ifdef ALLEGRO_ASM_PREFIX
00032 #define PREFIX ALLEGRO_ASM_PREFIX
00033 #else
00034 #define PREFIX
00035 #endif
00036 #if defined ALLEGRO_I386
00037
00038 #if defined ALLEGRO_GCC && !defined USE_PREASSEMBLED
00039
00040 asm("\n"
00041 PREFIX "agl_write_line_asm:\n"
00042 " pushl %ecx\n"
00043 " pushl %eax\n"
00044 " pushl %edx\n"
00045 " call " PREFIX "agl_write_line_c\n"
00046 " popl %edx\n"
00047 " popl %ecx\n"
00048 " popl %ecx\n"
00049 " ret\n"
00050 "\n"
00051 PREFIX "agl_unwrite_line_asm:\n"
00052 " pushl %eax\n"
00053 " pushl %ecx\n"
00054 " pushl %edx\n"
00055 " call " PREFIX "agl_unwrite_line_c\n"
00056 " popl %edx\n"
00057 " popl %ecx\n"
00058 " popl %eax\n"
00059 " ret\n"
00060 );
00061
00062 extern void agl_write_line_asm();
00063 extern void agl_unwrite_line_asm();
00064 static void *agl_write_line = agl_write_line_asm;
00065 static void *agl_unwrite_line = agl_unwrite_line_asm;
00066 #else
00067
00068
00069 unsigned char preassembled_code[] = {
00070 0x51, 0x50, 0x52,
00071 0xe8, 0, 0, 0, 0,
00072 0x5a, 0x59, 0x59,
00073 0xc3,
00074 0x50, 0x51, 0x52,
00075 0xe8, 0, 0, 0, 0,
00076 0x5a, 0x59, 0x58,
00077 0xc3
00078 };
00079 #define PREASM
00080 #define PREASM_OFFSET_WRITE_FUNC 4
00081 #define PREASM_OFFSET_UNWRITE_FUNC 16
00082 static void *agl_write_line = preassembled_code;
00083 static void *agl_unwrite_line = preassembled_code + 12;
00084 #endif
00085 #else
00086
00087
00088 static void *agl_write_line = NULL, *agl_unwrite_line = NULL;
00089 #endif
00090 #endif
00091
00092
00093
00094 static int screen_w, screen_h;
00095
00096
00097 static BITMAP *__allegro_gl_memory = NULL;
00098 static GFX_VTABLE memory_vtable;
00099 static int *dirty_flags = NULL;
00100 static int dirty_size = 0;
00101
00102
00103 int __allegro_gl_screen_mode = AGL_MODE_DIRECT;
00104
00105
00106 static int lastline = -1;
00107
00108
00109
00110
00111
00112 static unsigned long agl_write_line_c(BITMAP * bmp, int line)
00113 {
00114 switch (__allegro_gl_screen_mode) {
00115
00116 case AGL_MODE_DIRECT:
00117 break;
00118
00119 case AGL_MODE_DUPLEX:
00120
00121 if (lastline != -1)
00122 agl_unwrite_line_c(bmp);
00123 lastline = line;
00124
00125 glReadPixels(0, screen_h - lastline, screen_w, 1,
00126 __allegro_gl_get_bitmap_color_format(screen, 0),
00127 __allegro_gl_get_bitmap_type(screen, 0),
00128 bmp->line[lastline]);
00129
00130 break;
00131
00132 case AGL_MODE_OPAQUE:
00133 case AGL_MODE_MASKED:
00134
00135 dirty_flags[line] = 1;
00136 break;
00137
00138 case AGL_MODE_OPAQUE_RT:
00139 case AGL_MODE_MASKED_RT:
00140 if (lastline != -1)
00141 agl_unwrite_line_c(bmp);
00142 lastline = line;
00143 break;
00144
00145 }
00146 return (int) bmp->line[line];
00147 }
00148
00149
00150
00151
00152
00153
00154
00155 static void agl_unwrite_line_c(BITMAP * bmp)
00156 {
00157 switch (__allegro_gl_screen_mode) {
00158
00159 case AGL_MODE_DIRECT:
00160 break;
00161
00162 case AGL_MODE_DUPLEX:
00163 case AGL_MODE_OPAQUE_RT:
00164
00165 if (lastline != -1) {
00166 allegro_gl_begin();
00167 glRasterPos2i(0, lastline);
00168 glDrawPixels(screen_w, 1,
00169 __allegro_gl_get_bitmap_color_format(screen, 0),
00170 __allegro_gl_get_bitmap_type(screen, 0),
00171 bmp->line[lastline]);
00172 allegro_gl_end();
00173 lastline = -1;
00174 }
00175 break;
00176
00177 case AGL_MODE_MASKED_RT:
00178
00179 break;
00180
00181 case AGL_MODE_OPAQUE:
00182 case AGL_MODE_MASKED:
00183 break;
00184
00185 }
00186 }
00187
00188
00189
00190
00191
00192
00193
00194 static void prepare_for_blitting(void)
00195 {
00196 allegro_gl_begin();
00197
00198
00199
00200 glDisable(GL_ALPHA_TEST);
00201 glDisable(GL_BLEND);
00202 glDisable(GL_DEPTH_TEST);
00203 glDisable(GL_FOG);
00204 glDisable(GL_LIGHTING);
00205 #ifdef GL_COLOR_LOGIC_OP
00206 glDisable(GL_COLOR_LOGIC_OP);
00207 #endif
00208 glDisable(GL_STENCIL_TEST);
00209 glDisable(GL_TEXTURE_1D);
00210 glDisable(GL_TEXTURE_2D);
00211
00212 glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
00213 glPixelTransferi(GL_RED_SCALE, 1);
00214 glPixelTransferi(GL_RED_BIAS, 0);
00215 glPixelTransferi(GL_GREEN_SCALE, 1);
00216 glPixelTransferi(GL_GREEN_BIAS, 0);
00217 glPixelTransferi(GL_BLUE_SCALE, 1);
00218 glPixelTransferi(GL_BLUE_BIAS, 0);
00219 glPixelTransferi(GL_ALPHA_SCALE, 1);
00220 glPixelTransferi(GL_ALPHA_BIAS, 0);
00221
00222 glPixelZoom(1.0, 1.0);
00223
00224 allegro_gl_end();
00225 }
00226
00227
00228
00229
00230
00231
00232 static int init_screen_mode(int newmode)
00233 {
00234 switch (newmode) {
00235
00236 case AGL_MODE_DIRECT:
00237 screen = allegro_gl_screen;
00238 return 0;
00239
00240 case AGL_MODE_DUPLEX:
00241 screen = __allegro_gl_memory;
00242 prepare_for_blitting();
00243 return 0;
00244
00245 case AGL_MODE_OPAQUE:
00246 case AGL_MODE_OPAQUE_RT:
00247 screen = __allegro_gl_memory;
00248 clear_bitmap(screen);
00249 memset(dirty_flags, 0, dirty_size);
00250 return 0;
00251
00252 case AGL_MODE_MASKED:
00253 case AGL_MODE_MASKED_RT:
00254 screen = __allegro_gl_memory;
00255 clear_to_color(screen, bitmap_mask_color(screen));
00256 memset(dirty_flags, 0, dirty_size);
00257 return 0;
00258
00259 default:
00260 return -1;
00261
00262 }
00263 }
00264
00265
00266
00267
00268
00269
00270 static int shutdown_screen_mode(int oldmode)
00271 {
00272 switch (oldmode) {
00273
00274 case AGL_MODE_DIRECT:
00275 return 0;
00276
00277 case AGL_MODE_DUPLEX:
00278 case AGL_MODE_OPAQUE_RT:
00279 case AGL_MODE_MASKED_RT:
00280 if (lastline != -1)
00281 agl_unwrite_line_c(screen);
00282 return 0;
00283
00284 case AGL_MODE_OPAQUE:
00285 glRasterPos2i(0, 0);
00286 glDrawPixels(screen_w, screen_h,
00287 __allegro_gl_get_bitmap_color_format(screen, 0),
00288 __allegro_gl_get_bitmap_type(screen, 0), screen->line[0]);
00289 return 0;
00290
00291 case AGL_MODE_MASKED:
00292
00293 return 0;
00294
00295 default:
00296 return -1;
00297
00298 }
00299 }
00300
00301
00302
00392 int allegro_gl_screen_mode(int newmode)
00393 {
00394 return shutdown_screen_mode(__allegro_gl_screen_mode)
00395 || init_screen_mode(__allegro_gl_screen_mode = newmode);
00396 }
00397
00398
00399
00400
00401
00402
00403
00404 static void create_memory_screen(void)
00405 {
00406 __allegro_gl_memory = create_bitmap(screen_w, screen_h);
00407 if (!__allegro_gl_memory)
00408 return;
00409
00410 clear_bitmap(__allegro_gl_memory);
00411
00412 dirty_size = screen_h * sizeof *dirty_flags;
00413 dirty_flags = malloc(dirty_size);
00414 if (!dirty_flags) {
00415 destroy_bitmap(__allegro_gl_memory);
00416 __allegro_gl_memory = NULL;
00417 return;
00418 }
00419
00420 {
00421 int i;
00422 for (i = 0; i < screen_h; i++)
00423 dirty_flags[i] = 0;
00424 }
00425
00426 memcpy(&memory_vtable, __allegro_gl_memory->vtable, sizeof memory_vtable);
00427 __allegro_gl_memory->vtable = &memory_vtable;
00428 __allegro_gl_memory->write_bank = agl_write_line;
00429 __allegro_gl_memory->vtable->unwrite_bank = agl_unwrite_line;
00430 }
00431
00432
00433
00434
00435
00436
00437 void __allegro_gl_init_screen_mode(void)
00438 {
00439 static int initialised = 0;
00440 if (initialised) {
00441
00442 if (__allegro_gl_memory) {
00443 destroy_bitmap(__allegro_gl_memory);
00444 __allegro_gl_memory = NULL;
00445 free(dirty_flags);
00446 dirty_flags = NULL;
00447 }
00448 }
00449 else {
00450
00451 initialised = 1;
00452
00453 #ifdef PREASM
00454
00455
00456
00457 *(int *) (preassembled_code + PREASM_OFFSET_WRITE_FUNC) =
00458 (int) agl_write_line_c - (int) preassembled_code -
00459 PREASM_OFFSET_WRITE_FUNC - 4;
00460 *(int *) (preassembled_code + PREASM_OFFSET_UNWRITE_FUNC) =
00461 (int) agl_unwrite_line_c - (int) preassembled_code -
00462 PREASM_OFFSET_UNWRITE_FUNC - 4;
00463 #else
00464
00465 (void) agl_write_line_c;
00466 (void) agl_unwrite_line_c;
00467 #endif
00468 }
00469
00470 screen_w = allegro_gl_display_info.w;
00471 screen_h = allegro_gl_display_info.h;
00472 create_memory_screen();
00473
00474 init_screen_mode(AGL_MODE_DIRECT);
00475 }
00476
00477
00478
00479
00480
00481
00482
00483 void __allegro_gl_release_screen(void)
00484 {
00485 switch(__allegro_gl_screen_mode) {
00486
00487 case AGL_MODE_DIRECT:
00488
00489 if (__allegro_gl_memory)
00490 destroy_bitmap(__allegro_gl_memory);
00491 break;
00492
00493 case AGL_MODE_DUPLEX:
00494 case AGL_MODE_OPAQUE_RT:
00495 case AGL_MODE_MASKED_RT:
00496 case AGL_MODE_OPAQUE:
00497 case AGL_MODE_MASKED:
00498
00499 if (allegro_gl_screen)
00500 destroy_bitmap(allegro_gl_screen);
00501 break;
00502
00503 default:
00504 return;
00505
00506 }
00507
00508 if (dirty_flags)
00509 free(dirty_flags);
00510 dirty_flags = NULL;
00511
00512
00513
00514 __allegro_gl_memory = NULL;
00515 allegro_gl_screen = NULL;
00516 }
00517