| 1 | /*************************************************************************** |
| 2 | PluginGLView.m |
| 3 | PeopsSoftGPU |
| 4 | |
| 5 | Created by Gil Pedersen on Sun April 18 2004. |
| 6 | Copyright (c) 2004 Gil Pedersen. |
| 7 | ***************************************************************************/ |
| 8 | |
| 9 | /*************************************************************************** |
| 10 | * * |
| 11 | * This program is free software; you can redistribute it and/or modify * |
| 12 | * it under the terms of the GNU General Public License as published by * |
| 13 | * the Free Software Foundation; either version 2 of the License, or * |
| 14 | * (at your option) any later version. See also the license.txt file for * |
| 15 | * additional informations. * |
| 16 | * * |
| 17 | ***************************************************************************/ |
| 18 | |
| 19 | #import <OpenGL/gl.h> |
| 20 | #import <OpenGL/glext.h> |
| 21 | #import <OpenGL/glu.h> |
| 22 | #import <GLUT/glut.h> |
| 23 | #import <Carbon/Carbon.h> |
| 24 | #import "PluginGLView.h" |
| 25 | #include "externals.h" |
| 26 | #undef BOOL |
| 27 | #include "gpu.h" |
| 28 | #include "swap.h" |
| 29 | |
| 30 | #include <time.h> |
| 31 | extern time_t tStart; |
| 32 | |
| 33 | static int mylog2(int val) |
| 34 | { |
| 35 | int i; |
| 36 | for (i=1; i<31; i++) |
| 37 | if (val <= (1 << i)) |
| 38 | return (1 << i); |
| 39 | |
| 40 | return -1; |
| 41 | } |
| 42 | |
| 43 | #if 0 |
| 44 | void BlitScreen16NS(unsigned char * surf,long x,long y) |
| 45 | { |
| 46 | unsigned long lu; |
| 47 | unsigned short row,column; |
| 48 | unsigned short dx=PreviousPSXDisplay.Range.x1>>1; |
| 49 | unsigned short dy=PreviousPSXDisplay.DisplayMode.y; |
| 50 | unsigned short LineOffset,SurfOffset; |
| 51 | long lPitch=image_width<<1; |
| 52 | |
| 53 | if(PreviousPSXDisplay.Range.y0) // centering needed? |
| 54 | { |
| 55 | surf+=PreviousPSXDisplay.Range.y0*lPitch; |
| 56 | dy-=PreviousPSXDisplay.Range.y0; |
| 57 | } |
| 58 | |
| 59 | { |
| 60 | unsigned long * SRCPtr = (unsigned long *)(psxVuw + (y<<10) + x); |
| 61 | unsigned long * DSTPtr = ((unsigned long *)surf)+(PreviousPSXDisplay.Range.x0>>1); |
| 62 | |
| 63 | LineOffset = 512 - dx; |
| 64 | SurfOffset = (lPitch>>2) - dx; |
| 65 | |
| 66 | for(column=0;column<dy;column++) |
| 67 | { |
| 68 | for(row=0;row<dx;row++) |
| 69 | { |
| 70 | lu=GETLE16D(SRCPtr++); |
| 71 | |
| 72 | *DSTPtr++= lu;//((lu<<11)&0xf800f800)|((lu<<1)&0x7c007c0)|((lu>>10)&0x1f001f); |
| 73 | } |
| 74 | SRCPtr += LineOffset; |
| 75 | DSTPtr += SurfOffset; |
| 76 | } |
| 77 | } |
| 78 | } |
| 79 | #endif |
| 80 | |
| 81 | @implementation PluginGLView |
| 82 | |
| 83 | //- (id)initWithFrame:(NSRect)frameRect |
| 84 | - (id) initWithCoder: (NSCoder *) coder |
| 85 | { |
| 86 | const GLubyte * strExt; |
| 87 | |
| 88 | if ((self = [super initWithCoder:coder]) == nil) |
| 89 | return nil; |
| 90 | |
| 91 | glLock = [[NSLock alloc] init]; |
| 92 | if (nil == glLock) { |
| 93 | [self release]; |
| 94 | return nil; |
| 95 | } |
| 96 | |
| 97 | // Init pixel format attribs |
| 98 | NSOpenGLPixelFormatAttribute attrs[] = |
| 99 | { |
| 100 | NSOpenGLPFAAccelerated, |
| 101 | NSOpenGLPFANoRecovery, |
| 102 | NSOpenGLPFADoubleBuffer, |
| 103 | 0 |
| 104 | }; |
| 105 | |
| 106 | // Get pixel format from OpenGL |
| 107 | NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; |
| 108 | if (!pixFmt) |
| 109 | { |
| 110 | NSLog(@"No Accelerated OpenGL pixel format found\n"); |
| 111 | |
| 112 | NSOpenGLPixelFormatAttribute attrs2[] = |
| 113 | { |
| 114 | NSOpenGLPFANoRecovery, |
| 115 | 0 |
| 116 | }; |
| 117 | |
| 118 | // Get pixel format from OpenGL |
| 119 | pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs2]; |
| 120 | if (!pixFmt) { |
| 121 | NSLog(@"No OpenGL pixel format found!\n"); |
| 122 | |
| 123 | [self release]; |
| 124 | return nil; |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | [self setPixelFormat:[pixFmt autorelease]]; |
| 129 | |
| 130 | /* |
| 131 | long swapInterval = 1 ; |
| 132 | [[self openGLContext] |
| 133 | setValues:&swapInterval |
| 134 | forParameter:NSOpenGLCPSwapInterval]; |
| 135 | */ |
| 136 | [glLock lock]; |
| 137 | [[self openGLContext] makeCurrentContext]; |
| 138 | |
| 139 | // Init object members |
| 140 | strExt = glGetString (GL_EXTENSIONS); |
| 141 | texture_range = gluCheckExtension ((const unsigned char *)"GL_APPLE_texture_range", strExt) ? GL_TRUE : GL_FALSE; |
| 142 | texture_hint = GL_STORAGE_SHARED_APPLE ; |
| 143 | client_storage = gluCheckExtension ((const unsigned char *)"GL_APPLE_client_storage", strExt) ? GL_TRUE : GL_FALSE; |
| 144 | rect_texture = gluCheckExtension((const unsigned char *)"GL_EXT_texture_rectangle", strExt) ? GL_TRUE : GL_FALSE; |
| 145 | |
| 146 | // Setup some basic OpenGL stuff |
| 147 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
| 148 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); |
| 149 | glColor4f(1.0f, 1.0f, 1.0f, 1.0f); |
| 150 | glClearColor(0.0f, 0.0f, 0.0f, 1.0f); |
| 151 | glClear(GL_COLOR_BUFFER_BIT); |
| 152 | |
| 153 | [NSOpenGLContext clearCurrentContext]; |
| 154 | [glLock unlock]; |
| 155 | |
| 156 | image_width = 1024; |
| 157 | image_height = 512; |
| 158 | image_depth = 16; |
| 159 | |
| 160 | image_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; |
| 161 | image_base = (GLubyte *) calloc(((IMAGE_COUNT * image_width * image_height) / 3) * 4, image_depth >> 3); |
| 162 | if (image_base == nil) { |
| 163 | [self release]; |
| 164 | return nil; |
| 165 | } |
| 166 | |
| 167 | // Create and load textures for the first time |
| 168 | [self loadTextures:GL_TRUE]; |
| 169 | |
| 170 | // Init fps timer |
| 171 | //gettimeofday(&cycle_time, NULL); |
| 172 | |
| 173 | drawBG = YES; |
| 174 | |
| 175 | // Call for a redisplay |
| 176 | noDisplay = YES; |
| 177 | PSXDisplay.Disabled = 1; |
| 178 | [self setNeedsDisplay:true]; |
| 179 | |
| 180 | return self; |
| 181 | } |
| 182 | |
| 183 | - (void)dealloc |
| 184 | { |
| 185 | int i; |
| 186 | |
| 187 | [glLock lock]; |
| 188 | |
| 189 | [[self openGLContext] makeCurrentContext]; |
| 190 | for(i = 0; i < IMAGE_COUNT; i++) |
| 191 | { |
| 192 | GLuint dt = i+1; |
| 193 | glDeleteTextures(1, &dt); |
| 194 | } |
| 195 | if(texture_range) glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, IMAGE_COUNT * image_width * image_height * (image_depth >> 3), image_base); |
| 196 | |
| 197 | [NSOpenGLContext clearCurrentContext]; |
| 198 | [glLock unlock]; |
| 199 | [glLock release]; |
| 200 | |
| 201 | if (image_base) |
| 202 | free(image_base); |
| 203 | |
| 204 | [super dealloc]; |
| 205 | } |
| 206 | |
| 207 | - (BOOL)isOpaque |
| 208 | { |
| 209 | return YES; |
| 210 | } |
| 211 | |
| 212 | - (BOOL)acceptsFirstResponder |
| 213 | { |
| 214 | return NO; |
| 215 | } |
| 216 | |
| 217 | - (void)drawRect:(NSRect)aRect |
| 218 | { |
| 219 | // Check if an update has occured to the buffer |
| 220 | if ([self lockFocusIfCanDraw]) { |
| 221 | |
| 222 | // Make this context current |
| 223 | if (drawBG) { |
| 224 | [[NSColor blackColor] setFill]; |
| 225 | [NSBezierPath fillRect:[self visibleRect]]; |
| 226 | } |
| 227 | |
| 228 | //glFinish() ; |
| 229 | // Swap buffer to screen |
| 230 | //[[self openGLContext] flushBuffer]; |
| 231 | |
| 232 | [self unlockFocus]; |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | #if 0 |
| 237 | - (void)update // moved or resized |
| 238 | { |
| 239 | NSRect rect; |
| 240 | |
| 241 | [super update]; |
| 242 | |
| 243 | [[self openGLContext] makeCurrentContext]; |
| 244 | [[self openGLContext] update]; |
| 245 | |
| 246 | rect = [self bounds]; |
| 247 | |
| 248 | glViewport(0, 0, (int) rect.size.width, (int) rect.size.height); |
| 249 | |
| 250 | glMatrixMode(GL_PROJECTION); |
| 251 | glLoadIdentity(); |
| 252 | |
| 253 | glMatrixMode(GL_MODELVIEW); |
| 254 | glLoadIdentity(); |
| 255 | |
| 256 | //[self setNeedsDisplay:true]; |
| 257 | } |
| 258 | #endif |
| 259 | |
| 260 | - (void)reshape // scrolled, moved or resized |
| 261 | { |
| 262 | [glLock lock]; |
| 263 | |
| 264 | NSOpenGLContext *oglContext = [self openGLContext]; |
| 265 | NSRect rect; |
| 266 | |
| 267 | [super reshape]; |
| 268 | |
| 269 | [oglContext makeCurrentContext]; |
| 270 | [oglContext update]; |
| 271 | |
| 272 | rect = [[oglContext view] bounds]; |
| 273 | |
| 274 | glViewport(0, 0, (int) rect.size.width, (int) rect.size.height); |
| 275 | |
| 276 | glMatrixMode(GL_PROJECTION); |
| 277 | glLoadIdentity(); |
| 278 | |
| 279 | glMatrixMode(GL_MODELVIEW); |
| 280 | glLoadIdentity(); |
| 281 | |
| 282 | drawBG = YES; |
| 283 | |
| 284 | [NSOpenGLContext clearCurrentContext]; |
| 285 | |
| 286 | // [self setNeedsDisplay:true]; |
| 287 | |
| 288 | [self renderScreen]; |
| 289 | [glLock unlock]; |
| 290 | } |
| 291 | |
| 292 | - (void)renderScreen |
| 293 | { |
| 294 | int bufferIndex = whichImage; |
| 295 | |
| 296 | if (1/*[glLock tryLock]*/) { |
| 297 | // Make this context current |
| 298 | [[self openGLContext] makeCurrentContext]; |
| 299 | if (PSXDisplay.Disabled) { |
| 300 | glClear(GL_COLOR_BUFFER_BIT); |
| 301 | } else { |
| 302 | // Bind, update and draw new image |
| 303 | if(rect_texture) |
| 304 | { |
| 305 | glBindTexture(GL_TEXTURE_RECTANGLE_EXT, bufferIndex+1); |
| 306 | |
| 307 | glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, image_width, image_height, GL_BGRA, image_type, image[bufferIndex]); |
| 308 | glBegin(GL_QUADS); |
| 309 | glTexCoord2f(0.0f, 0.0f); |
| 310 | glVertex2f(-1.0f, 1.0f); |
| 311 | |
| 312 | glTexCoord2f(0.0f, image_height); |
| 313 | glVertex2f(-1.0f, -1.0f); |
| 314 | |
| 315 | glTexCoord2f(image_width, image_height); |
| 316 | glVertex2f(1.0f, -1.0f); |
| 317 | |
| 318 | glTexCoord2f(image_width, 0.0f); |
| 319 | glVertex2f(1.0f, 1.0f); |
| 320 | glEnd(); |
| 321 | } |
| 322 | else |
| 323 | { |
| 324 | glBindTexture(GL_TEXTURE_2D, whichImage+1); |
| 325 | |
| 326 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_width2, image_height2, GL_BGRA, image_type, image[bufferIndex]); |
| 327 | glBegin(GL_QUADS); |
| 328 | glTexCoord2f(0.0f, 0.0f); |
| 329 | glVertex2f(-1.0f, 1.0f); |
| 330 | |
| 331 | glTexCoord2f(0.0f, image_ty); |
| 332 | glVertex2f(-1.0f, -1.0f); |
| 333 | |
| 334 | glTexCoord2f(image_tx, image_ty); |
| 335 | glVertex2f(1.0f, -1.0f); |
| 336 | |
| 337 | glTexCoord2f(image_tx, 0.0f); |
| 338 | glVertex2f(1.0f, 1.0f); |
| 339 | glEnd(); |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | // FPS Display |
| 344 | if(ulKeybits&KEY_SHOWFPS) |
| 345 | { |
| 346 | int len, i; |
| 347 | if(szDebugText[0] && ((time(NULL) - tStart) < 2)) |
| 348 | { |
| 349 | strncpy(szDispBuf, szDebugText, 63); |
| 350 | } |
| 351 | else |
| 352 | { |
| 353 | szDebugText[0]=0; |
| 354 | if (szMenuBuf) { |
| 355 | strncat(szDispBuf, szMenuBuf, 63 - strlen(szDispBuf)); |
| 356 | } |
| 357 | } |
| 358 | |
| 359 | NSRect rect = [[[self openGLContext] view] bounds]; |
| 360 | len = (int) strlen(szDispBuf); |
| 361 | |
| 362 | glMatrixMode(GL_PROJECTION); |
| 363 | glPushMatrix(); |
| 364 | |
| 365 | gluOrtho2D(0.0, rect.size.width, 0.0, rect.size.height); |
| 366 | glDisable(rect_texture ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D); |
| 367 | |
| 368 | glColor4f(0.0, 0.0, 0.0, 0.5); |
| 369 | glRasterPos2f(3.0, rect.size.height - 14.0); |
| 370 | for (i = 0; i < len; i++) { |
| 371 | glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, szDispBuf[i]); |
| 372 | } |
| 373 | |
| 374 | glColor3f(1.0, 1.0, 1.0); |
| 375 | glRasterPos2f(2.0, rect.size.height - 13.0); |
| 376 | for (i = 0; i < len; i++) { |
| 377 | glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, szDispBuf[i]); |
| 378 | } |
| 379 | |
| 380 | |
| 381 | glEnable(rect_texture ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D); |
| 382 | glPopMatrix(); |
| 383 | } |
| 384 | |
| 385 | [[self openGLContext] flushBuffer]; |
| 386 | [NSOpenGLContext clearCurrentContext]; |
| 387 | //[glLock unlock]; |
| 388 | } |
| 389 | } |
| 390 | |
| 391 | - (void)loadTextures:(GLboolean)first |
| 392 | { |
| 393 | GLint i; |
| 394 | |
| 395 | //[glLock lock]; |
| 396 | [[self openGLContext] makeCurrentContext]; |
| 397 | |
| 398 | /* |
| 399 | printf("Range.x0=%i\n" |
| 400 | "Range.x1=%i\n" |
| 401 | "Range.y0=%i\n" |
| 402 | "Range.y1=%i\n", |
| 403 | PreviousPSXDisplay.Range.x0, |
| 404 | PreviousPSXDisplay.Range.x1, |
| 405 | PreviousPSXDisplay.Range.y0, |
| 406 | PreviousPSXDisplay.Range.y1); |
| 407 | |
| 408 | printf("DisplayMode.x=%d\n" |
| 409 | "DisplayMode.y=%d\n", |
| 410 | PreviousPSXDisplay.DisplayMode.x, |
| 411 | PreviousPSXDisplay.DisplayMode.y); |
| 412 | |
| 413 | printf("DisplayPosition.x=%i\n" |
| 414 | "DisplayPosition.y=%i\n", |
| 415 | PreviousPSXDisplay.DisplayPosition.x, |
| 416 | PreviousPSXDisplay.DisplayPosition.y); |
| 417 | |
| 418 | printf("DisplayEnd.x=%i\n" |
| 419 | "DisplayEnd.y=%i\n", |
| 420 | PreviousPSXDisplay.DisplayEnd.x, |
| 421 | PreviousPSXDisplay.DisplayEnd.y); |
| 422 | |
| 423 | printf("Double=%i\n" |
| 424 | "Height=%i\n", |
| 425 | PreviousPSXDisplay.Double, |
| 426 | PreviousPSXDisplay.Height); |
| 427 | |
| 428 | printf("Disabled=%i\n", PreviousPSXDisplay.Disabled); |
| 429 | */ |
| 430 | |
| 431 | image_width = PreviousPSXDisplay.Range.x1; |
| 432 | image_height = PreviousPSXDisplay.DisplayMode.y; |
| 433 | if (PSXDisplay.RGB24) { |
| 434 | image_depth = 32; |
| 435 | image_type = GL_UNSIGNED_INT_8_8_8_8_REV; |
| 436 | } else { |
| 437 | image_depth = 16; |
| 438 | image_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; |
| 439 | //image_width >>= 1; |
| 440 | } |
| 441 | |
| 442 | if (image_width * image_height * (image_depth >> 3) > ((1024*512*2)/3)*4) |
| 443 | printf("Fatal error: desired dimension are too large! (%ix%i %ibpp)\n", |
| 444 | image_width, image_height, image_depth); |
| 445 | |
| 446 | for(i = 0; i < IMAGE_COUNT; i++) |
| 447 | image[i] = image_base + i * image_width * image_height * (image_depth >> 3); |
| 448 | |
| 449 | if(rect_texture) |
| 450 | { |
| 451 | image_width2 = image_width; |
| 452 | image_height2 = image_height; |
| 453 | image_tx = (float)image_width; |
| 454 | image_ty = (float)image_height; |
| 455 | |
| 456 | if(texture_range) glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, IMAGE_COUNT * image_width * image_height * (image_depth >> 3), image_base); |
| 457 | else glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, 0, NULL); |
| 458 | |
| 459 | for(i = 0; i < IMAGE_COUNT; i++) |
| 460 | { |
| 461 | if(!first) |
| 462 | { |
| 463 | GLuint dt = i+1; |
| 464 | glDeleteTextures(1, &dt); |
| 465 | } |
| 466 | |
| 467 | glDisable(GL_TEXTURE_2D); |
| 468 | glEnable(GL_TEXTURE_RECTANGLE_EXT); |
| 469 | glBindTexture(GL_TEXTURE_RECTANGLE_EXT, i+1); |
| 470 | |
| 471 | glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , texture_hint); |
| 472 | glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, client_storage); |
| 473 | glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 474 | glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 475 | glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 476 | glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 477 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |
| 478 | |
| 479 | glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, image_width, |
| 480 | image_height, 0, GL_BGRA, image_type, image[i]); |
| 481 | } |
| 482 | } |
| 483 | else |
| 484 | { |
| 485 | image_width2 = mylog2(image_width); |
| 486 | image_height2 = mylog2(image_height); |
| 487 | image_tx = (float)image_width/(float)image_width2; |
| 488 | image_ty = (float)image_height/(float)image_height2; |
| 489 | |
| 490 | glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, 0, NULL); |
| 491 | if(texture_range) glTextureRangeAPPLE(GL_TEXTURE_2D, IMAGE_COUNT * image_width2 * image_height2 * (image_depth >> 3), image_base); |
| 492 | else glTextureRangeAPPLE(GL_TEXTURE_2D, 0, NULL); |
| 493 | |
| 494 | for(i = 0; i < IMAGE_COUNT; i++) |
| 495 | { |
| 496 | if(!first) |
| 497 | { |
| 498 | GLuint dt = i+1; |
| 499 | glDeleteTextures(1, &dt); |
| 500 | } |
| 501 | |
| 502 | glDisable(GL_TEXTURE_RECTANGLE_EXT); |
| 503 | glEnable(GL_TEXTURE_2D); |
| 504 | glBindTexture(GL_TEXTURE_2D, i+1); |
| 505 | |
| 506 | //if(texture_range) glTextureRangeAPPLE(GL_TEXTURE_2D, IMAGE_COUNT * image_width2 * image_height2 * (image_depth >> 3), image_base); |
| 507 | //else glTextureRangeAPPLE(GL_TEXTURE_2D, 0, NULL); |
| 508 | |
| 509 | glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , texture_hint); |
| 510 | glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, client_storage); |
| 511 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 512 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 513 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 514 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 515 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |
| 516 | |
| 517 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width2, |
| 518 | image_height2, 0, GL_BGRA, image_type, image[i]); |
| 519 | } |
| 520 | } |
| 521 | |
| 522 | [NSOpenGLContext clearCurrentContext]; |
| 523 | //[glLock unlock]; |
| 524 | } |
| 525 | |
| 526 | - (void)swapBuffer |
| 527 | { |
| 528 | unsigned char * surf; |
| 529 | long x = PSXDisplay.DisplayPosition.x; |
| 530 | long y = PSXDisplay.DisplayPosition.y; |
| 531 | unsigned long lu; |
| 532 | unsigned short row,column; |
| 533 | unsigned short dx=(unsigned short)PSXDisplay.DisplayEnd.x;//PreviousPSXDisplay.Range.x1; |
| 534 | unsigned short dy=(unsigned short)PSXDisplay.DisplayEnd.y;//PreviousPSXDisplay.DisplayMode.y; |
| 535 | long lPitch; |
| 536 | |
| 537 | //printf("y=%i",PSXDisplay.DisplayPosition.y); |
| 538 | |
| 539 | if ([glLock tryLock]) { |
| 540 | // make sure the texture area is ready to be written to |
| 541 | glFinishObjectAPPLE(GL_TEXTURE, 2-whichImage); |
| 542 | |
| 543 | if ((image_width != PreviousPSXDisplay.Range.x1) || |
| 544 | (image_height != PreviousPSXDisplay.DisplayMode.y) || |
| 545 | ((PSXDisplay.RGB24 ? 32 : 16) != image_depth)) { |
| 546 | [self loadTextures:NO]; |
| 547 | } |
| 548 | |
| 549 | surf = image[1-whichImage]; |
| 550 | lPitch=image_width2<<(image_depth >> 4); |
| 551 | |
| 552 | if(PreviousPSXDisplay.Range.y0) // centering needed? |
| 553 | { |
| 554 | surf+=PreviousPSXDisplay.Range.y0*lPitch; |
| 555 | dy-=PreviousPSXDisplay.Range.y0; |
| 556 | } |
| 557 | |
| 558 | if(PSXDisplay.RGB24) |
| 559 | { |
| 560 | unsigned char * pD;unsigned int startxy; |
| 561 | |
| 562 | surf+=PreviousPSXDisplay.Range.x0<<2; |
| 563 | |
| 564 | for(column=0;column<dy;column++) |
| 565 | { |
| 566 | startxy = (1024 * (column + y)) + x; |
| 567 | pD = (unsigned char *)&psxVuw[startxy]; |
| 568 | |
| 569 | row = 0; |
| 570 | // make sure the reads are aligned |
| 571 | while ((int)pD & 0x3) { |
| 572 | *((unsigned long *)((surf)+(column*lPitch)+(row<<2))) = |
| 573 | (*(pD+0)<<16)|(*(pD+1)<<8)|*(pD+2); |
| 574 | |
| 575 | pD+=3; |
| 576 | row++; |
| 577 | } |
| 578 | |
| 579 | for(;row<dx;row+=4) |
| 580 | { |
| 581 | unsigned long lu1 = *((unsigned long *)pD); |
| 582 | unsigned long lu2 = *((unsigned long *)pD+1); |
| 583 | unsigned long lu3 = *((unsigned long *)pD+2); |
| 584 | unsigned long *dst = ((unsigned long *)((surf)+(column*lPitch)+(row<<2))); |
| 585 | #ifdef __POWERPC__ |
| 586 | *(dst)= |
| 587 | (((lu1>>24)&0xff)<<16)|(((lu1>>16)&0xff)<<8)|(((lu1>>8)&0xff)); |
| 588 | *(dst+1)= |
| 589 | (((lu1>>0)&0xff)<<16)|(((lu2>>24)&0xff)<<8)|(((lu2>>16)&0xff)); |
| 590 | *(dst+2)= |
| 591 | (((lu2>>8)&0xff)<<16)|(((lu2>>0)&0xff)<<8)|(((lu3>>24)&0xff)); |
| 592 | *(dst+3)= |
| 593 | (((lu3>>16)&0xff)<<16)|(((lu3>>8)&0xff)<<8)|(((lu3>>0)&0xff)); |
| 594 | #else |
| 595 | *(dst)= |
| 596 | (((lu1>>0)&0xff)<<16)|(((lu1>>8)&0xff)<<8)|(((lu1>>16)&0xff)); |
| 597 | *(dst+1)= |
| 598 | (((lu1>>24)&0xff)<<16)|(((lu2>>0)&0xff)<<8)|(((lu2>>8)&0xff)); |
| 599 | *(dst+2)= |
| 600 | (((lu2>>16)&0xff)<<16)|(((lu2>>24)&0xff)<<8)|(((lu3>>0)&0xff)); |
| 601 | *(dst+3)= |
| 602 | (((lu3>>8)&0xff)<<16)|(((lu3>>16)&0xff)<<8)|(((lu3>>24)&0xff)); |
| 603 | #endif |
| 604 | pD+=12; |
| 605 | } |
| 606 | |
| 607 | //for(;row<dx;row+=4) |
| 608 | /*while (pD&0x3) { |
| 609 | *((unsigned long *)((surf)+(column*lPitch)+(row<<2)))= |
| 610 | (*(pD+0)<<16)|(*(pD+1)<<8)|(*(pD+2)&0xff)); |
| 611 | pD+=3; |
| 612 | row++; |
| 613 | }*/ |
| 614 | } |
| 615 | } |
| 616 | else |
| 617 | { |
| 618 | int LineOffset,SurfOffset; |
| 619 | unsigned long * SRCPtr = (unsigned long *)(psxVuw + (y << 10) + x); |
| 620 | unsigned long * DSTPtr = |
| 621 | ((unsigned long *)surf) + (PreviousPSXDisplay.Range.x0 >> 1); |
| 622 | |
| 623 | dx >>= 1; |
| 624 | |
| 625 | LineOffset = 512 - dx; |
| 626 | SurfOffset = (lPitch >> 2) - dx; |
| 627 | |
| 628 | for(column=0;column<dy;column++) |
| 629 | { |
| 630 | for(row=0;row<dx;row++) |
| 631 | { |
| 632 | #ifdef __POWERPC__ |
| 633 | lu=GETLE16D(SRCPtr++); |
| 634 | #else |
| 635 | lu=*SRCPtr++; |
| 636 | #endif |
| 637 | *DSTPtr++= |
| 638 | ((lu << 10) & 0x7c007c00)| |
| 639 | ((lu) & 0x3e003e0)| |
| 640 | ((lu >> 10) & 0x1f001f); |
| 641 | } |
| 642 | SRCPtr += LineOffset; |
| 643 | DSTPtr += SurfOffset; |
| 644 | } |
| 645 | } |
| 646 | |
| 647 | // Swap image buffer |
| 648 | whichImage = 1 - whichImage; |
| 649 | |
| 650 | [self renderScreen]; |
| 651 | [glLock unlock]; |
| 652 | } |
| 653 | } |
| 654 | |
| 655 | - (void)clearBuffer:(BOOL)display |
| 656 | { |
| 657 | if (display == NO) { |
| 658 | //[[self openGLContext] makeCurrentContext]; |
| 659 | //glClear(GL_COLOR_BUFFER_BIT); |
| 660 | //[self loadTextures:NO]; |
| 661 | } else { |
| 662 | noDisplay = YES; |
| 663 | // [self setNeedsDisplay:true]; |
| 664 | } |
| 665 | } |
| 666 | /* |
| 667 | - (void)mouseDown:(NSEvent *)theEvent |
| 668 | { |
| 669 | PluginWindowController *controller = [[self window] windowController]; |
| 670 | |
| 671 | static unsigned long lastTime = 0; |
| 672 | unsigned long time; |
| 673 | |
| 674 | time = TickCount(); |
| 675 | |
| 676 | if (lastTime != 0) { |
| 677 | if (time - lastTime > GetDblTime()) { |
| 678 | if (isFullscreen) { |
| 679 | [[self openGLContext] clearDrawable]; |
| 680 | } else { |
| 681 | [[self openGLContext] setFullScreen]; |
| 682 | } |
| 683 | isFullscreen = 1-isFullscreen; |
| 684 | lastTime = 0; |
| 685 | return; |
| 686 | } |
| 687 | } |
| 688 | |
| 689 | lastTime = time; |
| 690 | }*/ |
| 691 | |
| 692 | @end |