void OpenGLWindowProvider::flip(int interval) { OpenGL::set_active(get_gc()); glFlush(); if (shadow_window) { int width = get_viewport().get_width(); int height = get_viewport().get_height(); if (using_gl3) { if (double_buffered) { glDrawBuffer(GL_BACK); glReadBuffer(GL_FRONT); } PixelBuffer pixelbuffer(width, height, tf_bgra8); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, pixelbuffer.get_pitch() / pixelbuffer.get_bytes_per_pixel()); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glReadPixels( 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, pixelbuffer.get_data()); win32_window.update_layered(pixelbuffer); } else { GLint old_viewport[4], old_matrix_mode; GLfloat old_matrix_projection[16], old_matrix_modelview[16]; glGetIntegerv(GL_VIEWPORT, old_viewport); glGetIntegerv(GL_MATRIX_MODE, &old_matrix_mode); glGetFloatv(GL_PROJECTION_MATRIX, old_matrix_projection); glGetFloatv(GL_MODELVIEW_MATRIX, old_matrix_modelview); GLboolean blending = glIsEnabled(GL_BLEND); glDisable(GL_BLEND); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMultMatrixf(Mat4f::ortho_2d(0.0f, (float)width, 0.0f, (float)height, handed_right, clip_negative_positive_w)); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if (double_buffered) { glReadBuffer(GL_BACK); } glRasterPos2i(0, 0); glPixelZoom(1.0f, 1.0f); PixelBuffer pixelbuffer(width, height, tf_rgba8); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, pixelbuffer.get_pitch() / pixelbuffer.get_bytes_per_pixel()); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glReadPixels( 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixelbuffer.get_data()); win32_window.update_layered(pixelbuffer); if (blending) glEnable(GL_BLEND); glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]); glMatrixMode(GL_PROJECTION); glLoadMatrixf(old_matrix_projection); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(old_matrix_modelview); glMatrixMode(old_matrix_mode); } } else { if (interval != -1 && interval != swap_interval) { swap_interval = interval; if (wglSwapIntervalEXT) wglSwapIntervalEXT(swap_interval); } BOOL retval = SwapBuffers(get_device_context()); if (dwm_layered) { int width = get_viewport().get_width(); int height = get_viewport().get_height(); glReadBuffer(GL_FRONT); PixelBuffer pixelbuffer(width, height, tf_r8); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, pixelbuffer.get_pitch() / pixelbuffer.get_bytes_per_pixel()); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glReadPixels( 0, 0, width, height, GL_ALPHA, GL_BYTE, // use GL_BITMAP here for even less transfer? pixelbuffer.get_data()); win32_window.update_layered(pixelbuffer); } } OpenGL::check_error(); }
static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) { PlayState *ps = (PlayState *)ps_void; GHOST_TEventType type = GHOST_GetEventType(evt); int val; // print_ps(ps); playanim_event_qual_update(); /* convert ghost event into value keyboard or mouse */ val = ELEM(type, GHOST_kEventKeyDown, GHOST_kEventButtonDown); if (ps->wait2 && ps->stopped) { ps->stopped = FALSE; } if (ps->wait2) { pupdate_time(); ptottime = 0; } switch (type) { case GHOST_kEventKeyDown: case GHOST_kEventKeyUp: { GHOST_TEventKeyData *key_data; key_data = (GHOST_TEventKeyData *)GHOST_GetEventData(evt); switch (key_data->key) { case GHOST_kKeyA: if (val) ps->noskip = !ps->noskip; break; case GHOST_kKeyP: if (val) ps->pingpong = !ps->pingpong; break; case GHOST_kKey1: case GHOST_kKeyNumpad1: if (val) swaptime = ps->fstep / 60.0; break; case GHOST_kKey2: case GHOST_kKeyNumpad2: if (val) swaptime = ps->fstep / 50.0; break; case GHOST_kKey3: case GHOST_kKeyNumpad3: if (val) swaptime = ps->fstep / 30.0; break; case GHOST_kKey4: case GHOST_kKeyNumpad4: if (g_WS.qual & WS_QUAL_SHIFT) swaptime = ps->fstep / 24.0; else swaptime = ps->fstep / 25.0; break; case GHOST_kKey5: case GHOST_kKeyNumpad5: if (val) swaptime = ps->fstep / 20.0; break; case GHOST_kKey6: case GHOST_kKeyNumpad6: if (val) swaptime = ps->fstep / 15.0; break; case GHOST_kKey7: case GHOST_kKeyNumpad7: if (val) swaptime = ps->fstep / 12.0; break; case GHOST_kKey8: case GHOST_kKeyNumpad8: if (val) swaptime = ps->fstep / 10.0; break; case GHOST_kKey9: case GHOST_kKeyNumpad9: if (val) swaptime = ps->fstep / 6.0; break; case GHOST_kKeyLeftArrow: if (val) { ps->sstep = TRUE; ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { ps->picture = picsbase.first; ps->next_frame = 0; } else { ps->next_frame = -1; } } break; case GHOST_kKeyDownArrow: if (val) { ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { ps->next_frame = ps->direction = -1; } else { ps->next_frame = -10; ps->sstep = TRUE; } } break; case GHOST_kKeyRightArrow: if (val) { ps->sstep = TRUE; ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { ps->picture = picsbase.last; ps->next_frame = 0; } else { ps->next_frame = 1; } } break; case GHOST_kKeyUpArrow: if (val) { ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { ps->next_frame = ps->direction = 1; } else { ps->next_frame = 10; ps->sstep = TRUE; } } break; case GHOST_kKeySlash: case GHOST_kKeyNumpadSlash: if (val) { if (g_WS.qual & WS_QUAL_SHIFT) { if (ps->curframe_ibuf) printf(" Name: %s | Speed: %.2f frames/s\n", ps->curframe_ibuf->name, ps->fstep / swaptime); } else { swaptime = ps->fstep / 5.0; } } break; case GHOST_kKey0: case GHOST_kKeyNumpad0: if (val) { if (ps->once) { ps->once = ps->wait2 = FALSE; } else { ps->picture = NULL; ps->once = TRUE; ps->wait2 = FALSE; } } break; case GHOST_kKeyEnter: case GHOST_kKeyNumpadEnter: if (val) { ps->wait2 = ps->sstep = FALSE; } break; case GHOST_kKeyPeriod: case GHOST_kKeyNumpadPeriod: if (val) { if (ps->sstep) { ps->wait2 = FALSE; } else { ps->sstep = TRUE; ps->wait2 = !ps->wait2; } } break; case GHOST_kKeyEqual: case GHOST_kKeyNumpadPlus: { if (val == 0) break; if (g_WS.qual & WS_QUAL_CTRL) { playanim_window_zoom(ps, 1.0f); } else { swaptime /= 1.1; } break; } case GHOST_kKeyMinus: case GHOST_kKeyNumpadMinus: { if (val == 0) break; if (g_WS.qual & WS_QUAL_CTRL) { playanim_window_zoom(ps, -1.0f); } else { swaptime *= 1.1; } break; } case GHOST_kKeyEsc: ps->go = FALSE; break; default: break; } break; } case GHOST_kEventButtonDown: case GHOST_kEventButtonUp: { GHOST_TEventButtonData *bd = GHOST_GetEventData(evt); int cx, cy, sizex, sizey, inside_window; GHOST_GetCursorPosition(g_WS.ghost_system, &cx, &cy); GHOST_ScreenToClient(g_WS.ghost_window, cx, cy, &cx, &cy); playanim_window_get_size(&sizex, &sizey); inside_window = (cx >= 0 && cx < sizex && cy >= 0 && cy <= sizey); if (bd->button == GHOST_kButtonMaskLeft) { if (type == GHOST_kEventButtonDown) { if (inside_window) g_WS.qual |= WS_QUAL_LMOUSE; } else g_WS.qual &= ~WS_QUAL_LMOUSE; } else if (bd->button == GHOST_kButtonMaskMiddle) { if (type == GHOST_kEventButtonDown) { if (inside_window) g_WS.qual |= WS_QUAL_MMOUSE; } else g_WS.qual &= ~WS_QUAL_MMOUSE; } else if (bd->button == GHOST_kButtonMaskRight) { if (type == GHOST_kEventButtonDown) { if (inside_window) g_WS.qual |= WS_QUAL_RMOUSE; } else g_WS.qual &= ~WS_QUAL_RMOUSE; } break; } case GHOST_kEventCursorMove: { if (g_WS.qual & WS_QUAL_LMOUSE) { int sizex, sizey; int i; GHOST_TEventCursorData *cd = GHOST_GetEventData(evt); int cx, cy; GHOST_ScreenToClient(g_WS.ghost_window, cd->x, cd->y, &cx, &cy); playanim_window_get_size(&sizex, &sizey); ps->picture = picsbase.first; /* TODO - store in ps direct? */ i = 0; while (ps->picture) { i++; ps->picture = ps->picture->next; } i = (i * cx) / sizex; ps->picture = picsbase.first; for (; i > 0; i--) { if (ps->picture->next == NULL) break; ps->picture = ps->picture->next; } ps->sstep = TRUE; ps->wait2 = FALSE; ps->next_frame = 0; } break; } case GHOST_kEventWindowActivate: case GHOST_kEventWindowDeactivate: { g_WS.qual &= ~WS_QUAL_MOUSE; break; } case GHOST_kEventWindowSize: case GHOST_kEventWindowMove: { float zoomx, zoomy; playanim_window_get_size(&ps->win_x, &ps->win_y); GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); zoomx = (float) ps->win_x / ps->ibufx; zoomy = (float) ps->win_y / ps->ibufy; /* zoom always show entire image */ ps->zoom = MIN2(zoomx, zoomy); /* zoom steps of 2 for speed */ ps->zoom = floor(ps->zoom + 0.5f); if (ps->zoom < 1.0f) ps->zoom = 1.0f; glViewport(0, 0, ps->win_x, ps->win_y); glScissor(0, 0, ps->win_x, ps->win_y); /* unified matrix, note it affects offset for drawing */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glPixelZoom(ps->zoom, ps->zoom); ptottime = 0.0; playanim_toscreen(ps, ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep); break; } case GHOST_kEventQuit: case GHOST_kEventWindowClose: { ps->go = FALSE; break; } case GHOST_kEventDraggingDropDone: { GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt); if (ddd->dataType == GHOST_kDragnDropTypeFilenames) { GHOST_TStringArray *stra = ddd->data; int a; for (a = 0; a < stra->count; a++) { BLI_strncpy(ps->dropped_file, (char *)stra->strings[a], sizeof(ps->dropped_file)); ps->go = FALSE; printf("drop file %s\n", stra->strings[a]); break; /* only one drop element supported now */ } } break; } default: /* quiet warnings */ break; } return 1; }
PsychError SCREENPutImage(void) { PsychRectType windowRect, positionRect; int ix, iy; size_t matrixRedIndex, matrixGreenIndex, matrixBlueIndex, matrixAlphaIndex, matrixGrayIndex; int inputM, inputN, inputP, positionRectWidth, positionRectHeight; size_t pixelIndex = 0; PsychWindowRecordType *windowRecord; unsigned char *inputMatrixByte; double *inputMatrixDouble; GLfloat *pixelData; GLfloat matrixGrayValue, matrixRedValue, matrixGreenValue, matrixBlueValue, matrixAlphaValue; PsychArgFormatType inputMatrixType; GLfloat xZoom = 1, yZoom = -1; // All sub functions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if (PsychIsGiveHelp()) { PsychGiveHelp(); return PsychError_none; }; // Cap the number of inputs. PsychErrorExit(PsychCapNumInputArgs(4)); //The maximum number of inputs PsychErrorExit(PsychCapNumOutputArgs(0)); //The maximum number of outputs // Get the image matrix. inputMatrixType = PsychGetArgType(2); switch (inputMatrixType) { case PsychArgType_none: case PsychArgType_default: PsychErrorExitMsg(PsychError_user, "imageArray argument required"); break; case PsychArgType_uint8: PsychAllocInUnsignedByteMatArg(2, TRUE, &inputM, &inputN, &inputP, &inputMatrixByte); break; case PsychArgType_double: PsychAllocInDoubleMatArg(2, TRUE, &inputM, &inputN, &inputP, &inputMatrixDouble); break; default: PsychErrorExitMsg(PsychError_user, "imageArray must be uint8 or double type"); break; } if (inputP != 1 && inputP != 3 && inputP != 4) { PsychErrorExitMsg(PsychError_user, "Third dimension of image matrix must be 1, 3, or 4"); } // Get the window and get the rect and stuff. PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); // A no-go on OES: if (PsychIsGLES(windowRecord)) { PsychErrorExitMsg(PsychError_unimplemented, "Sorry, Screen('PutImage') is not supported on OpenGL-ES embedded graphics hardware. Use 'MakeTexture' and 'DrawTexture' instead."); } PsychGetRectFromWindowRecord(windowRect, windowRecord); if (PsychCopyInRectArg(3, FALSE, positionRect)) { if (IsPsychRectEmpty(positionRect)) { return PsychError_none; } positionRectWidth = (int) PsychGetWidthFromRect(positionRect); positionRectHeight = (int) PsychGetHeightFromRect(positionRect); if (positionRectWidth != inputN || positionRectHeight != inputM) { // Calculate the zoom factor. xZoom = (GLfloat) positionRectWidth / (GLfloat) inputN; yZoom = -((GLfloat) positionRectHeight / (GLfloat) inputM); } } else { positionRect[kPsychLeft] = 0; positionRect[kPsychTop] = 0; positionRect[kPsychRight] = inputN; positionRect[kPsychBottom] = inputM; PsychCenterRect(positionRect, windowRect, positionRect); } // Allocate memory to hold the pixel data that we'll later pass to OpenGL. pixelData = (GLfloat*) PsychMallocTemp(sizeof(GLfloat) * (size_t) inputN * (size_t) inputM * 4); // Loop through all rows and columns of the pixel data passed from Matlab, extract it, // and stick it into 'pixelData'. for (iy = 0; iy < inputM; iy++) { for (ix = 0; ix < inputN; ix++) { if (inputP == 1) { // Grayscale // Extract the grayscale value. matrixGrayIndex = PSYCHINDEXELEMENTFROM3DARRAY((size_t) inputM, (size_t) inputN, 1, (size_t) iy, (size_t) ix, 0); if (inputMatrixType == PsychArgType_uint8) { // If the color range is > 255, then force it to 255 for 8-bit values. matrixGrayValue = (GLfloat)inputMatrixByte[matrixGrayIndex]; if (windowRecord->colorRange > 255) { matrixGrayValue /= (GLfloat)255; } else { matrixGrayValue /= (GLfloat)windowRecord->colorRange; } } else { matrixGrayValue = (GLfloat)(inputMatrixDouble[matrixGrayIndex] / windowRecord->colorRange); } // RGB will all be the same for grayscale. We'll go ahead and fix alpha to the max value. pixelData[pixelIndex++] = matrixGrayValue; // R pixelData[pixelIndex++] = matrixGrayValue; // G pixelData[pixelIndex++] = matrixGrayValue; // B pixelData[pixelIndex++] = (GLfloat) 1.0; // A } else if (inputP == 3) { // RGB matrixRedIndex = PSYCHINDEXELEMENTFROM3DARRAY((size_t) inputM, (size_t) inputN, 3, (size_t) iy, (size_t) ix, 0); matrixGreenIndex = PSYCHINDEXELEMENTFROM3DARRAY((size_t) inputM, (size_t) inputN, 3, (size_t) iy, (size_t) ix, 1); matrixBlueIndex = PSYCHINDEXELEMENTFROM3DARRAY((size_t) inputM, (size_t) inputN, 3, (size_t) iy, (size_t) ix, 2); if (inputMatrixType == PsychArgType_uint8) { // If the color range is > 255, then force it to 255 for 8-bit values. matrixRedValue = (GLfloat)inputMatrixByte[matrixRedIndex]; matrixGreenValue = (GLfloat)inputMatrixByte[matrixGreenIndex]; matrixBlueValue = (GLfloat)inputMatrixByte[matrixBlueIndex]; if (windowRecord->colorRange > 255) { matrixRedValue /= (GLfloat)255; matrixGreenValue /= (GLfloat)255; matrixBlueValue /= (GLfloat)255; } else { matrixRedValue /= (GLfloat)windowRecord->colorRange; matrixGreenValue /= (GLfloat)windowRecord->colorRange; matrixBlueValue /= (GLfloat)windowRecord->colorRange; } } else { matrixRedValue = (GLfloat)(inputMatrixDouble[matrixRedIndex] / windowRecord->colorRange); matrixGreenValue = (GLfloat)(inputMatrixDouble[matrixGreenIndex] / windowRecord->colorRange); matrixBlueValue = (GLfloat)(inputMatrixDouble[matrixBlueIndex] / windowRecord->colorRange); } pixelData[pixelIndex++] = matrixRedValue; pixelData[pixelIndex++] = matrixGreenValue; pixelData[pixelIndex++] = matrixBlueValue; pixelData[pixelIndex++] = (GLfloat)1.0; } else if (inputP == 4) { // RGBA matrixRedIndex = PSYCHINDEXELEMENTFROM3DARRAY((size_t) inputM, (size_t) inputN, 4, (size_t) iy, (size_t) ix, 0); matrixGreenIndex = PSYCHINDEXELEMENTFROM3DARRAY((size_t) inputM, (size_t) inputN, 4, (size_t) iy, (size_t) ix, 1); matrixBlueIndex = PSYCHINDEXELEMENTFROM3DARRAY((size_t) inputM, (size_t) inputN, 4, (size_t) iy, (size_t) ix, 2); matrixAlphaIndex = PSYCHINDEXELEMENTFROM3DARRAY((size_t) inputM, (size_t) inputN, 4, (size_t) iy, (size_t) ix, 3); if (inputMatrixType == PsychArgType_uint8) { // If the color range is > 255, then force it to 255 for 8-bit values. matrixRedValue = (GLfloat)inputMatrixByte[matrixRedIndex]; matrixGreenValue = (GLfloat)inputMatrixByte[matrixGreenIndex]; matrixBlueValue = (GLfloat)inputMatrixByte[matrixBlueIndex]; matrixAlphaValue = (GLfloat)inputMatrixByte[matrixAlphaIndex]; if (windowRecord->colorRange > 255) { matrixRedValue /= (GLfloat)255; matrixGreenValue /= (GLfloat)255; matrixBlueValue /= (GLfloat)255; matrixAlphaValue /= (GLfloat)255; } else { matrixRedValue /= (GLfloat)windowRecord->colorRange; matrixGreenValue /= (GLfloat)windowRecord->colorRange; matrixBlueValue /= (GLfloat)windowRecord->colorRange; matrixAlphaValue /= (GLfloat)windowRecord->colorRange; } } else { matrixRedValue = (GLfloat)(inputMatrixDouble[matrixRedIndex] / windowRecord->colorRange); matrixGreenValue = (GLfloat)(inputMatrixDouble[matrixGreenIndex] / (GLfloat)windowRecord->colorRange); matrixBlueValue = (GLfloat)(inputMatrixDouble[matrixBlueIndex] / (GLfloat)windowRecord->colorRange); matrixAlphaValue = (GLfloat)(inputMatrixDouble[matrixAlphaIndex] / (GLfloat)windowRecord->colorRange); } pixelData[pixelIndex++] = matrixRedValue; pixelData[pixelIndex++] = matrixGreenValue; pixelData[pixelIndex++] = matrixBlueValue; pixelData[pixelIndex++] = matrixAlphaValue; } } // for (iy = 0; iy < inputM; iy++) } // for (ix = 0; ix < inputN; ix++) // Enable this windowRecords framebuffer as current drawingtarget: PsychSetDrawingTarget(windowRecord); // Disable draw shader: PsychSetShader(windowRecord, 0); PsychUpdateAlphaBlendingFactorLazily(windowRecord); // Set the raster position so that we can draw starting at this location. glRasterPos2f((GLfloat)(positionRect[kPsychLeft]), (GLfloat)(positionRect[kPsychTop])); // Tell glDrawPixels to unpack the pixel array along GLfloat boundaries. glPixelStorei(GL_UNPACK_ALIGNMENT, (GLint)sizeof(GLfloat)); // Dump the pixels onto the screen. glPixelZoom(xZoom, yZoom); glDrawPixels(inputN, inputM, GL_RGBA, GL_FLOAT, pixelData); glPixelZoom(1,1); PsychFlushGL(windowRecord); // This does nothing if we are multi buffered, otherwise it glFlushes PsychTestForGLErrors(); return PsychError_none; }
void displayFunc(void) { if (g_pause) return; /* create random geometry for regression test */ if (g_regression) g_render_scene = createRandomScene(g_device,1,random<int>()%100,random<int>()%1000); /* set accumulation mode */ int accumulate = g_resetAccumulation ? 0 : g_refine; g_resetAccumulation = false; /* render image */ Handle<Device::RTCamera> camera = createCamera(AffineSpace3f(g_camSpace.l,g_camSpace.p)); /* render into framebuffer */ g_device->rtRenderFrame(g_renderer,camera,g_render_scene,g_tonemapper,g_frameBuffer,accumulate); g_device->rtSwapBuffers(g_frameBuffer); /* draw image in OpenGL */ void* ptr = g_device->rtMapFrameBuffer(g_frameBuffer); // extern double upload_time; // upload_time = getSeconds() - upload_time; // std::cout << "upload " << upload_time << std::endl; // exit(0); glRasterPos2i(-1, 1); glPixelZoom(1.0f, -1.0f); if (g_format == "RGB_FLOAT32") glDrawPixels((GLsizei)g_width,(GLsizei)g_height,GL_RGB,GL_FLOAT,ptr); else if (g_format == "RGBA8") glDrawPixels((GLsizei)g_width,(GLsizei)g_height,GL_RGBA,GL_UNSIGNED_BYTE,ptr); else if (g_format == "RGB8") glDrawPixels((GLsizei)g_width,(GLsizei)g_height,GL_RGB,GL_UNSIGNED_BYTE,ptr); else throw std::runtime_error("unknown framebuffer format: "+g_format); glFlush(); glutSwapBuffers(); g_device->rtUnmapFrameBuffer(g_frameBuffer); /* calculate rendering time */ double t1 = getSeconds(); g_dt[frameID % avgFrames] = t1-g_t0; g_t0 = t1; frameID++; /* print average render time of previous frames */ size_t num = 0; double dt = 0.0f; for (size_t i=0; i<avgFrames; i++) { if (g_dt[i] != 0.0f) { dt += g_dt[i]; num++; } } dt /= num; std::ostringstream stream; stream.setf(std::ios::fixed, std::ios::floatfield); stream.precision(2); stream << 1.0f/dt << " fps, "; stream.precision(2); stream << dt*1000.0f << " ms"; stream << ", " << g_width << "x" << g_height; if (log_display) std::cout << "display " << stream.str() << std::endl; glutSetWindowTitle((std::string("Embree: ") + stream.str()).c_str()); }
static void display_text_draw(struct font_freetype_text *text, struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, int color, struct point *p) { int i, x, y, stride; struct font_freetype_glyph *g, **gp; unsigned char *shadow, *glyph; struct color transparent = { 0x0000, 0x0000, 0x0000, 0x0000 }; struct color black = { fg->fr * 65535, fg->fg * 65535, fg->fb * 65535, fg->fa * 65535 }; struct color white = { 0xffff, 0xffff, 0xffff, 0xffff }; if (bg) { if (COLOR_IS_WHITE(black) && COLOR_IS_BLACK(white)) { black.r = 65535; black.g = 65535; black.b = 65535; black.a = 65535; white.r = 0; white.g = 0; white.b = 0; white.a = 65535; } else if (COLOR_IS_BLACK(black) && COLOR_IS_WHITE(white)) { white.r = 65535; white.g = 65535; white.b = 65535; white.a = 65535; black.r = 0; black.g = 0; black.b = 0; black.a = 65535; } else { white.r = bg->fr; white.g = bg->fg; white.b = bg->fb; white.a = bg->fa; } } else { white.r = 0; white.g = 0; white.b = 0; white.a = 0; } gp = text->glyph; i = text->glyph_count; x = p->x << 6; y = p->y << 6; while (i-- > 0) { g = *gp++; if (g->w && g->h && bg) { stride = (g->w + 2) * 4; if (color) { shadow = g_malloc(stride * (g->h + 2)); gr->freetype_methods.get_shadow(g, shadow, 32, stride, &white, &transparent); #if USE_OPENGLES struct point p; p.x=((x + g->x) >> 6)-1; p.y=((y + g->y) >> 6)-1; draw_image_es(gr, &p, g->w+2, g->h+2, shadow); #else #ifdef MIRRORED_VIEW glPixelZoom(-1.0, -1.0); //mirrored mode #else glPixelZoom(1.0, -1.0); #endif glRasterPos2d((x + g->x) >> 6, (y + g->y) >> 6); glDrawPixels(g->w + 2, g->h + 2, PIXEL_FORMAT, GL_UNSIGNED_BYTE, shadow); #endif g_free(shadow); } } x += g->dx; y += g->dy; }
/* * PsychComposeCompressedStereoBuffer - Final compositing for compressed stereo. * * This routine copies both AUX buffers (0 and 1) back into the backbuffer, each of them * vertically scaled/compressed by a factor of 2. Its called by PsychPreFlipOperations(). */ void PsychComposeCompressedStereoBuffer(PsychWindowRecordType *windowRecord) { /* if (FALSE) { // Upload, setup and enable Anaglyph stereo fragment shader: const float redgain=1.0, greengain=0.7, bluegain=0.0; // This is the shader source code: const char anaglyphshader[] = "!!ARBfp1.0 " "PARAM ColorToGrayWeights = { 0.3, 0.59, 0.11, 1.0 }; " "TEMP luminance; " "TEMP incolor;" //"MOV incolor, fragment.color;" "TEX incolor, fragment.texcoord[0], texture[0], RECT;" "DP3 luminance, incolor, ColorToGrayWeights; " "MUL result.color.rgb, luminance, program.env[0]; " "MOV result.color.a, ColorToGrayWeights.a; " //"MOV result.color.a, fragment.color.a; " "END"; // Upload and compile shader: PsychTestForGLErrors(); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(anaglyphshader), anaglyphshader); PsychTestForGLErrors(); // Setup the rgb-gains as global parameters for the shader: glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, redgain, greengain, bluegain, 0.0); // Enable the shader: glEnable(GL_FRAGMENT_PROGRAM_ARB); } */ // Query screen dimension: int screenwidth=(int) PsychGetWidthFromRect(windowRecord->rect); int screenheight=(int) PsychGetHeightFromRect(windowRecord->rect); // When entering this routine, the modelview matrix is already set to identity and // the proper OpenGL context is active. // Set up zoom for vertical compression: glPixelZoom(1, 0.5f); glDrawBuffer(GL_BACK); glDisable(GL_BLEND); // Draw left view aka AUX0: glReadBuffer(GL_AUX0); glRasterPos2i(0, (windowRecord->stereomode==kPsychCompressedTLBRStereo) ? screenheight/2 : screenheight); glCopyPixels(0, 0, screenwidth, screenheight, GL_COLOR); // Draw right view aka AUX1: glReadBuffer(GL_AUX1); glRasterPos2i(0, (windowRecord->stereomode==kPsychCompressedTLBRStereo) ? screenheight : screenheight/2); glCopyPixels(0, 0, screenwidth, screenheight, GL_COLOR); // Restore settings: glReadBuffer(GL_BACK); glPixelZoom(1,1); glEnable(GL_BLEND); // Unconditionally disable fragment shaders: // glDisable(GL_FRAGMENT_PROGRAM_ARB); // Done. return; }
void render_view3d_draw(RenderEngine *engine, const bContext *C) { Render *re = engine->re; RenderResult rres; char name[32]; render_view3d_do(engine, C); if (re == NULL) { sprintf(name, "View3dPreview %p", (void *)CTX_wm_region(C)); re = RE_GetRender(name); if (re == NULL) return; } /* Viewport render preview doesn't support multiview, view hardcoded to 0 */ RE_AcquireResultImage(re, &rres, 0); if (rres.rectf) { RegionView3D *rv3d = CTX_wm_region_view3d(C); View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); bool force_fallback = false; bool need_fallback = true; float dither = scene->r.dither_intensity; float scale_x, scale_y; rcti clip_rect; int xof, yof; if (render_view3d_disprect(scene, ar, v3d, rv3d, &clip_rect)) { scale_x = (float) BLI_rcti_size_x(&clip_rect) / rres.rectx; scale_y = (float) BLI_rcti_size_y(&clip_rect) / rres.recty; xof = clip_rect.xmin; yof = clip_rect.ymin; } else { scale_x = (float) ar->winx / rres.rectx; scale_y = (float) ar->winy / rres.recty; xof = rres.xof; yof = rres.yof; } /* If user decided not to use GLSL, fallback to glaDrawPixelsAuto */ force_fallback |= (U.image_draw_method != IMAGE_DRAW_METHOD_GLSL); /* Try using GLSL display transform. */ if (force_fallback == false) { if (IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, dither, true)) { glEnable(GL_BLEND); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glPixelZoom(scale_x, scale_y); glaDrawPixelsTex(xof, yof, rres.rectx, rres.recty, GL_RGBA, GL_FLOAT, GL_NEAREST, rres.rectf); glPixelZoom(1.0f, 1.0f); glDisable(GL_BLEND); IMB_colormanagement_finish_glsl_draw(); need_fallback = false; } } /* If GLSL failed, use old-school CPU-based transform. */ if (need_fallback) { unsigned char *display_buffer = MEM_mallocN(4 * rres.rectx * rres.recty * sizeof(char), "render_view3d_draw"); IMB_colormanagement_buffer_make_display_space(rres.rectf, display_buffer, rres.rectx, rres.recty, 4, dither, &scene->view_settings, &scene->display_settings); glEnable(GL_BLEND); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glPixelZoom(scale_x, scale_y); glaDrawPixelsAuto(xof, yof, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); glPixelZoom(1.0f, 1.0f); glDisable(GL_BLEND); MEM_freeN(display_buffer); } } RE_ReleaseResultImage(re); }
int paint_image(Stimulus *st, Substim *sst) { int w,h,frame; double c; if(st->xstate == INTERLEAVE_EXPT_BLANK){ if(testflags[TEST_RC]) glClearColor(0, 0, 0, 1.0); else glClearColor(st->gammaback, st->gammaback, st->gammaback, 1.0); glClear(GL_COLOR_BUFFER_BIT); return(0); } if (st->prev != NULL) frame = st->prev->framectr+200; else{ frame = st->framectr; if(st->preload & frame > st->preloaded) frame = st->preloaded; } /* if(optionflags[FAST_SEQUENCE] & expt.vals[FAST_SEQUENCE_RPT] > 1) frame = floor(st->framectr/expt.vals[FAST_SEQUENCE_RPT]); */ if(st->stimid > -1000){ glPixelZoom(1.0,-1.0); if(st->preload){ w= imagews[frame]; h= imagews[frame]; } else{ w = sst->imw; h = sst->imh; } if(sst->pos.contrast < 0.99){ c = sst->pos.contrast; glPixelTransferf(GL_RED_BIAS,0.5-c/2); glPixelTransferf(GL_RED_SCALE,c); glPixelTransferf(GL_BLUE_BIAS,0.5-c/2); glPixelTransferf(GL_BLUE_SCALE,c); glPixelTransferf(GL_GREEN_BIAS,0.5-c/2); glPixelTransferf(GL_GREEN_SCALE, c); // glPixelTransferf(GL_GREEN_SCALE, 1.0); } else{ glPixelTransferf(GL_RED_BIAS,0); glPixelTransferf(GL_RED_SCALE,1); glPixelTransferf(GL_BLUE_BIAS,0); glPixelTransferf(GL_BLUE_SCALE,1); glPixelTransferf(GL_GREEN_BIAS,0); glPixelTransferf(GL_GREEN_SCALE, 1); } glRasterPos2i(sst->pos.xy[0]-w/2,sst->pos.xy[1]+h/2); if(st->preload){ if (sst->mode == RIGHTMODE && st->flag & UNCORRELATE) glDrawPixels(imagews[frame], imagehs[frame], GL_LUMINANCE, GL_UNSIGNED_BYTE, rightimages[frame]); else glDrawPixels(imagews[frame], imagehs[frame], GL_LUMINANCE, GL_UNSIGNED_BYTE, images[frame]); } else glDrawPixels(sst->imw, sst->imh, GL_LUMINANCE, GL_UNSIGNED_BYTE, sst->uimage); } sst->calculated = 0; return(sst->imw); }
static void HandleDisplay(void) { const WebPDecBuffer* const pic = kParams.pic; const WebPIterator* const curr = &kParams.curr_frame; WebPIterator* const prev = &kParams.prev_frame; GLfloat xoff, yoff; if (pic == NULL) return; glPushMatrix(); glPixelZoom((GLfloat)(+1. / kParams.canvas_width * kParams.viewport_width), (GLfloat)(-1. / kParams.canvas_height * kParams.viewport_height)); xoff = (GLfloat)(2. * curr->x_offset / kParams.canvas_width); yoff = (GLfloat)(2. * curr->y_offset / kParams.canvas_height); glRasterPos2f(-1.f + xoff, 1.f - yoff); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4); if (kParams.only_deltas) { DrawBackground(); } else { // The rectangle of the previous frame might be different than the current // frame, so we may need to DrawBackgroundScissored for both. if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { // Clear the previous frame rectangle. DrawBackgroundScissored(prev->x_offset, prev->y_offset, prev->width, prev->height); } if (curr->blend_method == WEBP_MUX_NO_BLEND) { // We simulate no-blending behavior by first clearing the current frame // rectangle and then alpha-blending against it. DrawBackgroundScissored(curr->x_offset, curr->y_offset, curr->width, curr->height); } } *prev = *curr; glDrawPixels(pic->width, pic->height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)pic->u.RGBA.rgba); if (kParams.print_info) { char tmp[32]; glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glRasterPos2f(-0.95f, 0.90f); PrintString(kParams.file_name); snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height); glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glRasterPos2f(-0.95f, 0.80f); PrintString(tmp); if (curr->x_offset != 0 || curr->y_offset != 0) { snprintf(tmp, sizeof(tmp), " (offset:%d,%d)", curr->x_offset, curr->y_offset); glRasterPos2f(-0.95f, 0.70f); PrintString(tmp); } } glPopMatrix(); #if defined(__APPLE__) || defined(_WIN32) glFlush(); #else glutSwapBuffers(); #endif }
static void HandleDisplay(void) { const WebPDecBuffer* const pic = kParams.pic; const WebPIterator* const curr = &kParams.curr_frame; WebPIterator* const prev = &kParams.prev_frame; GLfloat xoff, yoff; if (pic == NULL) return; glPushMatrix(); glPixelZoom(1, -1); xoff = (GLfloat)(2. * curr->x_offset / kParams.canvas_width); yoff = (GLfloat)(2. * curr->y_offset / kParams.canvas_height); glRasterPos2f(-1.f + xoff, 1.f - yoff); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4); if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND || curr->blend_method == WEBP_MUX_NO_BLEND) { // TODO(later): these offsets and those above should factor in window size. // they will be incorrect if the window is resized. // glScissor() takes window coordinates (0,0 at bottom left). int window_x, window_y; int frame_w, frame_h; if (prev->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { // Clear the previous frame rectangle. window_x = prev->x_offset; window_y = kParams.canvas_height - prev->y_offset - prev->height; frame_w = prev->width; frame_h = prev->height; } else { // curr->blend_method == WEBP_MUX_NO_BLEND. // We simulate no-blending behavior by first clearing the current frame // rectangle (to a checker-board) and then alpha-blending against it. window_x = curr->x_offset; window_y = kParams.canvas_height - curr->y_offset - curr->height; frame_w = curr->width; frame_h = curr->height; } glEnable(GL_SCISSOR_TEST); // Only update the requested area, not the whole canvas. glScissor(window_x, window_y, frame_w, frame_h); glClear(GL_COLOR_BUFFER_BIT); // use clear color DrawCheckerBoard(); glDisable(GL_SCISSOR_TEST); } *prev = *curr; glDrawPixels(pic->width, pic->height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)pic->u.RGBA.rgba); if (kParams.print_info) { char tmp[32]; glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glRasterPos2f(-0.95f, 0.90f); PrintString(kParams.file_name); snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height); glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glRasterPos2f(-0.95f, 0.80f); PrintString(tmp); if (curr->x_offset != 0 || curr->y_offset != 0) { snprintf(tmp, sizeof(tmp), " (offset:%d,%d)", curr->x_offset, curr->y_offset); glRasterPos2f(-0.95f, 0.70f); PrintString(tmp); } } glPopMatrix(); glFlush(); }
void ImageDisplay::paintGL() { #ifdef NICE_USELIB_GLUT setGLProjection(); if ( image != NULL ) { glPixelStorei ( GL_PACK_ALIGNMENT, 1 ); glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); glPixelZoom ( ( GLfloat ) width() / ( ( GLfloat ) image->width() ), ( ( GLfloat ) - height() ) / ( ( GLfloat ) image->height() ) ); glRasterPos2f ( 0, height() - 0.5 ); if ( isColor ) { glDrawPixels ( image->width(), image->height(), GL_RGB, GL_UNSIGNED_BYTE, image->getPixelPointer() ); } else { glDrawPixels ( image->width(), image->height(), GL_LUMINANCE, GL_UNSIGNED_BYTE, image->getPixelPointer() ); } } else { glClearColor ( 0.0, 0.0, 0.0, 0.0 ); glClear ( GL_COLOR_BUFFER_BIT ); glFlush(); } if ( buf_overlayImage != NULL ) { if ( image == NULL ) { glPixelStorei ( GL_PACK_ALIGNMENT, 1 ); glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); glPixelZoom ( ( GLfloat ) width() / ( ( GLfloat ) overlayImageWidth ), ( ( GLfloat ) - height() ) / ( ( GLfloat ) overlayImageHeight ) ); glRasterPos2f ( 0, height() - 0.5 ); } glEnable ( GL_BLEND ); glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glDrawPixels ( overlayImageWidth, overlayImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf_overlayImage ); glDisable ( GL_BLEND ); glFlush(); } if ( isDragging && drawSelectionRect ) { glLineWidth ( 1 ); glEnable ( GL_LINE_STIPPLE ); glLineStipple ( 1, 0x00FF ); glColor4f ( 1, 1, 1, 1 ); // // Antialiased Points // glEnable(GL_POINT_SMOOTH); // glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); // // Antialiased Lines // glEnable(GL_LINE_SMOOTH); // glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glBegin ( GL_LINE_LOOP ); glVertex2f ( dragX, height() - dragY ); glVertex2f ( dragX, height() - dropY ); glVertex2f ( dropX, height() - dropY ); glVertex2f ( dropX, height() - dragY ); glEnd(); glDisable ( GL_LINE_STIPPLE ); glFlush(); } if ( texts.size() > 0 ) { glEnable ( GL_BLEND ); glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); for ( uint i = 0; i < texts.size(); ++i ) { Text& text = texts[i]; glColor4ub ( text.color[0], text.color[1], text.color[2], 255 ); float x = float ( text.x ) * float ( width() ) / float ( image->width() ); float y = float ( text.y ) * float ( height() ) / float ( image->height() ); glRasterPos2f ( x, height() - y - 0.5 ); void* font = GLUT_BITMAP_HELVETICA_10;//(*i)->font; for ( uint j = 0; j < text.text.size(); ++j ) glutBitmapCharacter ( font, text.text[j] ); } glDisable ( GL_BLEND ); glFlush(); } #else fthrow(Exception,"GLUT lib not availabe, recompile using GLUT!"); #endif paintGLObjects(); }
void osm_pi::DoDrawBitmap( const wxBitmap &bitmap, wxCoord x, wxCoord y, bool usemask ) { if ( m_pdc ) { wxLogMessage (_T("OSM_PI: DoDrawBitmap %i,%i"),x,y); m_pdc->DrawBitmap( bitmap, x, y, usemask ); } else { wxLogMessage (_T("OSM_PI: DoDrawBitmapGL %i,%i"),x,y); // GL doesn't draw anything if x<0 || y<0 so we must crop image first wxBitmap bmp; if ( x < 0 || y < 0 ) { int dx = (x < 0 ? -x : 0); int dy = (y < 0 ? -y : 0); int w = bitmap.GetWidth()-dx; int h = bitmap.GetHeight()-dy; /* picture is out of viewport */ if ( w <= 0 || h <= 0 ) return; wxBitmap newBitmap = bitmap.GetSubBitmap( wxRect( dx, dy, w, h ) ); x += dx; y += dy; bmp = newBitmap; } else { bmp = bitmap; } wxImage image = bmp.ConvertToImage(); int w = image.GetWidth(), h = image.GetHeight(); if ( usemask ) { unsigned char *d = image.GetData(); unsigned char *a = image.GetAlpha(); unsigned char mr, mg, mb; if( !image.GetOrFindMaskColour( &mr, &mg, &mb ) && !a ) printf("trying to use mask to draw a bitmap without alpha or mask\n"); unsigned char *e = new unsigned char[4*w*h]; // int w = image.GetWidth(), h = image.GetHeight(); int sb = w*h; unsigned char r, g, b; for ( int i=0 ; i<sb ; i++ ) { r = d[i*3 + 0]; g = d[i*3 + 1]; b = d[i*3 + 2]; e[i*4 + 0] = r; e[i*4 + 1] = g; e[i*4 + 2] = b; e[i*4 + 3] = a ? a[i] : ((r==mr)&&(g==mg)&&(b==mb) ? 0 : 255); } glColor4f( 1, 1, 1, 1 ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glRasterPos2i( x, y ); glPixelZoom( 1, -1 ); glDrawPixels( w, h, GL_RGBA, GL_UNSIGNED_BYTE, e ); glPixelZoom( 1, 1 ); glDisable( GL_BLEND ); free( e ); } else { glRasterPos2i( x, y ); glPixelZoom( 1, -1 ); /* draw data from top to bottom */ glDrawPixels( w, h, GL_RGB, GL_UNSIGNED_BYTE, image.GetData() ); glPixelZoom( 1, 1 ); } } }
void bicubic2x(int gHeight, int gWidth, int h, int w, int xRes, int yRes, int max, unsigned char gData[]) { GLubyte color[2*gHeight][2*gWidth][4]; glClearColor(0.0, 0.0, 0.0, 0.0); //GLubyte color[gHeight][gWidth][4]; for(int y = 0; y < gHeight; y++) { for (int x = 0; x < gWidth; x ++) { int index = 4 * x + (4 * w * y); for (int xPixel = 0; xPixel < 2; xPixel++) { for (int yPixel = 0; yPixel < 2; yPixel++) { color[2*y + yPixel][2*x + xPixel][0] = int(gData[index]); color[2*y + yPixel][2*x + xPixel][1] = int(gData[index + 1]); color[2*y + yPixel][2*x + xPixel][2] = int(gData[index + 2]); color[2*y + yPixel][2*x + xPixel][3] = int(gData[index + 3]); } } int upIndex = getUpNeighbor(x,y, gWidth, gHeight); int downIndex = getDownNeighbor(x,y, gWidth, gHeight); int leftIndex = getLeftNeighbor(x,y, gWidth, gHeight); int rightIndex = getRightNeighbor(x,y, gWidth, gHeight); // this is for the edge cases if (upIndex == -1 || downIndex == -1 || leftIndex == -1 || rightIndex == -1) { // we'll just keep the same color for the pixels on the the border (already set) // note that we could change the interpolation to take the missing interpolatoin into // account..but this would be a lot of casework for little benefit } else { Vec3 up, down, right, left; up.x = gData[upIndex]; up.y = gData[upIndex+1]; up.z = gData[upIndex+2]; down.x = gData[downIndex]; down.y = gData[downIndex+1]; down.z = gData[downIndex+2]; right.x = gData[rightIndex]; right.y = gData[rightIndex+1]; right.z = gData[rightIndex+2]; left.x = gData[leftIndex]; left.y = gData[leftIndex+1]; left.z = gData[leftIndex+2]; Vec3 current; current.x = int(gData[index]); current.y = int(gData[index+1]); current.z = int(gData[index+2]); // we expand each pixel into 4 pixels, and then for each of the new pixels, // we interpolate with each neighbor in a 2x2 block. // originally, we have pixel P: /* |U| U1 U2 ----- ---------- L|P|R ----> L1 | P1 | P3 | R1 ----- L2 | P2 | P4 | R2 |D| ---------- D1 D2 Let U1 = U2 = U, L1 = L2 = L, R1 = R2 = R, D1 = D2 = D (we just expanded U, L, R, D as well) Let P = P1 = P2 = P3 = P4 (we just expanded pixel P) Now, we interpolate each of the P_i according to its 4 neigbors. We do a cubic interpolation in each direction (horiztonal and vertical) according to the 2 neighbors on either side. Order is important as CubicInterpolateVec(y0, y1, y2, y3, m) interpolates and returns the value m fraction of the way between y1 and y2. We use Catmoll-Rom spline interpolation, and then we make sure to clamp our RGB values between 0 and 255 before assigning the new colors. Note that we don't really care about alpha values here. */ // P2 Vec3 P2Left = CubicInterpolateVec(left, left, current, right, 0.5); Vec3 P2Up = CubicInterpolateVec(up, current, down, down, 0.5); int finalP2X = min(std::max((int)(P2Left.x + P2Up.x)/2, 0), 255); int finalP2Y = min(std::max((int)(P2Left.y + P2Up.y)/2, 0), 255); int finalP2Z = min(std::max((int)(P2Left.z + P2Up.z)/2, 0), 255); color[2*y][2*x][0] = finalP2X; color[2*y][2*x][1] = finalP2Y; color[2*y][2*x][2] = finalP2Z; color[2*y][2*x][3] = 255; // P4 Vec3 P4Left = CubicInterpolateVec(left, current, right, right, 0.5); Vec3 P4Up = CubicInterpolateVec(up, current, down, down, 0.5); int finalP4X = min(std::max((int)(P4Left.x + P4Up.x)/2, 0), 255); int finalP4Y = min(std::max((int)(P4Left.y + P4Up.y)/2, 0), 255); int finalP4Z = min(std::max((int)(P4Left.z + P4Up.z)/2, 0), 255); color[2*y][2*x + 1][0] = finalP4X; color[2*y][2*x + 1][1] = finalP4Y; color[2*y][2*x + 1][2] = finalP4Z; color[2*y][2*x + 1][3] = 255; // P1 Vec3 P1Left = CubicInterpolateVec(left, left, current, right, 0.5); Vec3 P1Up = CubicInterpolateVec(up, up, current, down, 0.5); int finalP1X = min(std::max((int)(P1Left.x + P1Up.x)/2, 0), 255); int finalP1Y = min(std::max((int)(P1Left.y + P1Up.y)/2, 0), 255); int finalP1Z = min(std::max((int)(P1Left.z + P1Up.z)/2, 0), 255); color[2*y + 1][2*x][0] = finalP1X; color[2*y + 1][2*x][1] = finalP1Y; color[2*y + 1][2*x][2] = finalP1Z; color[2*y + 1][2*x][3] = 255; // P3 Vec3 P3Left = CubicInterpolateVec(left, current, right, right, 0.5); Vec3 P3Up = CubicInterpolateVec(up, up, current, down, 0.5); int finalP3X = min(std::max((int)(P3Left.x + P3Up.x)/2, 0), 255); int finalP3Y = min(std::max((int)(P3Left.y + P3Up.y)/2, 0), 255); int finalP3Z = min(std::max((int)(P3Left.z + P3Up.z)/2, 0), 255); color[2*y + 1][2*x + 1][0] = finalP3X; color[2*y + 1][2*x + 1][1] = finalP3Y; color[2*y + 1][2*x + 1][2] = finalP3Z; color[2*y + 1][2*x + 1][3] = 255; } } } glPixelZoom(floor(xRes/max)/2, floor(yRes/max)/2); glRasterPos2d(-1.0, -1.0); glClear(GL_COLOR_BUFFER_BIT); glDrawPixels( 2*gWidth, 2*gHeight, GL_RGBA, GL_UNSIGNED_BYTE, color ); glFlush(); }
int YabSaveState(const char *filename) { u32 i; FILE *fp; int offset; IOCheck_struct check; u8 *buf; int totalsize; int outputwidth; int outputheight; int movieposition; int temp; u32 temp32; check.done = 0; check.size = 0; //use a second set of savestates for movies filename = MakeMovieStateName(filename); if (!filename) return -1; if ((fp = fopen(filename, "wb")) == NULL) return -1; // Write signature fprintf(fp, "YSS"); // Write endianness byte #ifdef WORDS_BIGENDIAN fputc(0x00, fp); #else fputc(0x01, fp); #endif // Write version(fix me) i = 2; ywrite(&check, (void *)&i, sizeof(i), 1, fp); // Skip the next 4 bytes for now i = 0; ywrite(&check, (void *)&i, sizeof(i), 1, fp); //write frame number ywrite(&check, (void *)&framecounter, 4, 1, fp); //this will be updated with the movie position later ywrite(&check, (void *)&framecounter, 4, 1, fp); // Go through each area and write each state i += CartSaveState(fp); i += Cs2SaveState(fp); i += SH2SaveState(MSH2, fp); i += SH2SaveState(SSH2, fp); i += SoundSaveState(fp); i += ScuSaveState(fp); i += SmpcSaveState(fp); i += Vdp1SaveState(fp); i += Vdp2SaveState(fp); offset = StateWriteHeader(fp, "OTHR", 1); // Other data ywrite(&check, (void *)BupRam, 0x10000, 1, fp); // do we really want to save this? ywrite(&check, (void *)HighWram, 0x100000, 1, fp); ywrite(&check, (void *)LowWram, 0x100000, 1, fp); ywrite(&check, (void *)&yabsys.DecilineCount, sizeof(int), 1, fp); ywrite(&check, (void *)&yabsys.LineCount, sizeof(int), 1, fp); ywrite(&check, (void *)&yabsys.VBlankLineCount, sizeof(int), 1, fp); ywrite(&check, (void *)&yabsys.MaxLineCount, sizeof(int), 1, fp); temp = yabsys.DecilineStop >> YABSYS_TIMING_BITS; ywrite(&check, (void *)&temp, sizeof(int), 1, fp); temp = (yabsys.CurSH2FreqType == CLKTYPE_26MHZ) ? 268 : 286; ywrite(&check, (void *)&temp, sizeof(int), 1, fp); temp32 = (yabsys.UsecFrac * temp / 10) >> YABSYS_TIMING_BITS; ywrite(&check, (void *)&temp32, sizeof(u32), 1, fp); ywrite(&check, (void *)&yabsys.CurSH2FreqType, sizeof(int), 1, fp); ywrite(&check, (void *)&yabsys.IsPal, sizeof(int), 1, fp); VIDCore->GetGlSize(&outputwidth, &outputheight); totalsize=outputwidth * outputheight * sizeof(u32); if ((buf = (u8 *)malloc(totalsize)) == NULL) { return -2; } YuiSwapBuffers(); #ifdef USE_OPENGL glPixelZoom(1,1); glReadBuffer(GL_BACK); glReadPixels(0, 0, outputwidth, outputheight, GL_RGBA, GL_UNSIGNED_BYTE, buf); #endif YuiSwapBuffers(); ywrite(&check, (void *)&outputwidth, sizeof(outputwidth), 1, fp); ywrite(&check, (void *)&outputheight, sizeof(outputheight), 1, fp); ywrite(&check, (void *)buf, totalsize, 1, fp); movieposition=ftell(fp); //write the movie to the end of the savestate SaveMovieInState(fp, check); i += StateFinishHeader(fp, offset); // Go back and update size fseek(fp, 8, SEEK_SET); ywrite(&check, (void *)&i, sizeof(i), 1, fp); fseek(fp, 16, SEEK_SET); ywrite(&check, (void *)&movieposition, sizeof(movieposition), 1, fp); fclose(fp); OSDPushMessage(OSDMSG_STATUS, 150, "STATE SAVED"); return 0; }
void drawGlutScene_from_image ( /****************************************************/ float ***p6, /* in : RGB image */ GLubyte *pixels, /* use : display array */ float magnify, /* in : scaling factor */ int nx, /* in : size in x-direction */ int ny, /* in : size in y-direction */ int bx, /* in : boundary size in x-direction */ int by /* in : boundary size in y-direction */ /****************************************************/ ) /* visualises image with Open-GL */ { int odd; /* flag for odd image size */ int counter; /* pixel index counter */ int i,j; /* loop variable */ /* check if image size is odd */ if (nx%4==0) odd=0; else odd=1; /* set pixel counter zero */ counter=0; /* prepare Open-GL */ glViewport(0, 0, nx, ny); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, nx, 0, ny, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glDisable(GL_DITHER); glPixelZoom((GLfloat)magnify,(GLfloat)magnify); /* draw pixels in pixel array */ for(i=by; i < ny+by; i++) { for(j=bx; j < nx+bx; j++) { pixels[counter++]=(GLubyte)(p6[j][ny+2*by-1-i][0]); pixels[counter++]=(GLubyte)(p6[j][ny+2*by-1-i][1]); pixels[counter++]=(GLubyte)(p6[j][ny+2*by-1-i][2]); } if (odd==1) counter+=2; } /* draw pixels in draw buffer */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.0, 0.0, 0.0, 1.0); glRasterPos3f(0, 0, 0.0); glDrawPixels(nx,ny,GL_RGB,GL_UNSIGNED_BYTE,pixels); /* swap draw and display buffer */ glutSwapBuffers(); return; }
static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, int width, int height, float zoomx, float zoomy) { int x, y; MovieClip *clip = ED_space_clip_get_clip(sc); /* find window pixel coordinates of origin */ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); if (sc->flag & SC_MUTE_FOOTAGE) { glColor3f(0.0f, 0.0f, 0.0f); glRectf(x, y, x + zoomx * width, y + zoomy * height); } else { verify_buffer_float(ibuf); if (ibuf->rect) { int need_fallback = 1; if (ED_space_clip_texture_buffer_supported(sc)) { if (ED_space_clip_load_movieclip_buffer(sc, ibuf)) { glPushMatrix(); glTranslatef(x, y, 0.0f); glScalef(zoomx, zoomy, 1.0f); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex2f(width, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex2f(width, height); glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, height); glEnd(); glPopMatrix(); ED_space_clip_unload_movieclip_buffer(sc); need_fallback = 0; } } /* if texture buffers aren't efficiently supported or texture is too large to * be binder fallback to simple draw pixels solution */ if (need_fallback) { /* set zoom */ glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y); glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); /* reset zoom */ glPixelZoom(1.0f, 1.0f); } } } /* draw boundary border for frame if stabilization is enabled */ if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) { glColor3f(0.0f, 0.0f, 0.0f); glLineStipple(3, 0xaaaa); glEnable(GL_LINE_STIPPLE); glEnable(GL_COLOR_LOGIC_OP); glLogicOp(GL_NOR); glPushMatrix(); glTranslatef(x, y, 0.0f); glScalef(zoomx, zoomy, 1.0f); glMultMatrixf(sc->stabmat); glBegin(GL_LINE_LOOP); glVertex2f(0.0f, 0.0f); glVertex2f(width, 0.0f); glVertex2f(width, height); glVertex2f(0.0f, height); glEnd(); glPopMatrix(); glDisable(GL_COLOR_LOGIC_OP); glDisable(GL_LINE_STIPPLE); } }
int YabLoadState(const char *filename) { FILE *fp; char id[3]; u8 endian; int headerversion, version, size, chunksize, headersize; IOCheck_struct check; u8* buf; int totalsize; int outputwidth; int outputheight; int curroutputwidth; int curroutputheight; int movieposition; int temp; u32 temp32; filename = MakeMovieStateName(filename); if (!filename) return -1; if ((fp = fopen(filename, "rb")) == NULL) return -1; headersize = 0xC; // Read signature yread(&check, (void *)id, 1, 3, fp); if (strncmp(id, "YSS", 3) != 0) { fclose(fp); return -2; } // Read header yread(&check, (void *)&endian, 1, 1, fp); yread(&check, (void *)&headerversion, 4, 1, fp); yread(&check, (void *)&size, 4, 1, fp); switch(headerversion) { case 1: /* This is the "original" version of the format */ break; case 2: /* version 2 adds video recording */ yread(&check, (void *)&framecounter, 4, 1, fp); movieposition=ftell(fp); yread(&check, (void *)&movieposition, 4, 1, fp); headersize = 0x14; break; default: /* we're trying to open a save state using a future version * of the YSS format, that won't work, sorry :) */ fclose(fp); return -3; break; } #ifdef WORDS_BIGENDIAN if (endian == 1) #else if (endian == 0) #endif { // should setup reading so it's byte-swapped YabSetError(YAB_ERR_OTHER, (void *)"Load State byteswapping not supported"); fclose(fp); return -3; } // Make sure size variable matches actual size minus header fseek(fp, 0, SEEK_END); if (size != (ftell(fp) - headersize)) { fclose(fp); return -2; } fseek(fp, headersize, SEEK_SET); // Verify version here ScspMuteAudio(SCSP_MUTE_SYSTEM); if (StateCheckRetrieveHeader(fp, "CART", &version, &chunksize) != 0) { fclose(fp); // Revert back to old state here ScspUnMuteAudio(SCSP_MUTE_SYSTEM); return -3; } CartLoadState(fp, version, chunksize); if (StateCheckRetrieveHeader(fp, "CS2 ", &version, &chunksize) != 0) { fclose(fp); // Revert back to old state here ScspUnMuteAudio(SCSP_MUTE_SYSTEM); return -3; } Cs2LoadState(fp, version, chunksize); if (StateCheckRetrieveHeader(fp, "MSH2", &version, &chunksize) != 0) { fclose(fp); // Revert back to old state here ScspUnMuteAudio(SCSP_MUTE_SYSTEM); return -3; } SH2LoadState(MSH2, fp, version, chunksize); if (StateCheckRetrieveHeader(fp, "SSH2", &version, &chunksize) != 0) { fclose(fp); // Revert back to old state here ScspUnMuteAudio(SCSP_MUTE_SYSTEM); return -3; } SH2LoadState(SSH2, fp, version, chunksize); if (StateCheckRetrieveHeader(fp, "SCSP", &version, &chunksize) != 0) { fclose(fp); // Revert back to old state here ScspUnMuteAudio(SCSP_MUTE_SYSTEM); return -3; } SoundLoadState(fp, version, chunksize); if (StateCheckRetrieveHeader(fp, "SCU ", &version, &chunksize) != 0) { fclose(fp); // Revert back to old state here ScspUnMuteAudio(SCSP_MUTE_SYSTEM); return -3; } ScuLoadState(fp, version, chunksize); if (StateCheckRetrieveHeader(fp, "SMPC", &version, &chunksize) != 0) { fclose(fp); // Revert back to old state here ScspUnMuteAudio(SCSP_MUTE_SYSTEM); return -3; } SmpcLoadState(fp, version, chunksize); if (StateCheckRetrieveHeader(fp, "VDP1", &version, &chunksize) != 0) { fclose(fp); // Revert back to old state here ScspUnMuteAudio(SCSP_MUTE_SYSTEM); return -3; } Vdp1LoadState(fp, version, chunksize); if (StateCheckRetrieveHeader(fp, "VDP2", &version, &chunksize) != 0) { fclose(fp); // Revert back to old state here ScspUnMuteAudio(SCSP_MUTE_SYSTEM); return -3; } Vdp2LoadState(fp, version, chunksize); if (StateCheckRetrieveHeader(fp, "OTHR", &version, &chunksize) != 0) { fclose(fp); // Revert back to old state here ScspUnMuteAudio(SCSP_MUTE_SYSTEM); return -3; } // Other data yread(&check, (void *)BupRam, 0x10000, 1, fp); yread(&check, (void *)HighWram, 0x100000, 1, fp); yread(&check, (void *)LowWram, 0x100000, 1, fp); yread(&check, (void *)&yabsys.DecilineCount, sizeof(int), 1, fp); yread(&check, (void *)&yabsys.LineCount, sizeof(int), 1, fp); yread(&check, (void *)&yabsys.VBlankLineCount, sizeof(int), 1, fp); yread(&check, (void *)&yabsys.MaxLineCount, sizeof(int), 1, fp); yread(&check, (void *)&temp, sizeof(int), 1, fp); yread(&check, (void *)&temp, sizeof(int), 1, fp); yread(&check, (void *)&temp32, sizeof(u32), 1, fp); yread(&check, (void *)&yabsys.CurSH2FreqType, sizeof(int), 1, fp); yread(&check, (void *)&yabsys.IsPal, sizeof(int), 1, fp); YabauseChangeTiming(yabsys.CurSH2FreqType); yabsys.UsecFrac = (temp32 << YABSYS_TIMING_BITS) * temp / 10; if (headerversion > 1) { yread(&check, (void *)&outputwidth, sizeof(outputwidth), 1, fp); yread(&check, (void *)&outputheight, sizeof(outputheight), 1, fp); totalsize=outputwidth * outputheight * sizeof(u32); if ((buf = (u8 *)malloc(totalsize)) == NULL) { return -2; } yread(&check, (void *)buf, totalsize, 1, fp); YuiSwapBuffers(); #ifdef USE_OPENGL if(VIDCore->id == VIDCORE_SOFT) glRasterPos2i(0, outputheight); if(VIDCore->id == VIDCORE_OGL) glRasterPos2i(0, outputheight/2); #endif VIDCore->GetGlSize(&curroutputwidth, &curroutputheight); #ifdef USE_OPENGL glPixelZoom((float)curroutputwidth / (float)outputwidth, ((float)curroutputheight / (float)outputheight)); glDrawPixels(outputwidth, outputheight, GL_RGBA, GL_UNSIGNED_BYTE, buf); #endif YuiSwapBuffers(); fseek(fp, movieposition, SEEK_SET); MovieReadState(fp, filename); } fclose(fp); ScspUnMuteAudio(SCSP_MUTE_SYSTEM); OSDPushMessage(OSDMSG_STATUS, 150, "STATE LOADED"); return 0; }
// // This function is called when the window needs redrawing. // static void Display(void) { ARdouble p[16]; ARdouble m[16]; #ifdef ARDOUBLE_IS_FLOAT GLdouble p0[16]; GLdouble m0[16]; #endif int i, j, k; GLfloat w, bw, bh, vertices[6][2]; GLubyte pixels[300]; char text[256]; GLdouble winX, winY, winZ; int showMErr[CHECK_ID_MULTIMARKERS_MAX]; GLdouble MX[CHECK_ID_MULTIMARKERS_MAX]; GLdouble MY[CHECK_ID_MULTIMARKERS_MAX]; int pattDetectMode; AR_MATRIX_CODE_TYPE matrixCodeType; // Select correct buffer for this context. glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the buffers for new frame. arglPixelBufferDataUpload(gArglSettings, gARTImage); arglDispImage(gArglSettings); if (gMultiConfigCount) { arglCameraFrustumRH(&(gCparamLT->param), VIEW_DISTANCE_MIN, VIEW_DISTANCE_MAX, p); glMatrixMode(GL_PROJECTION); #ifdef ARDOUBLE_IS_FLOAT glLoadMatrixf(p); #else glLoadMatrixd(p); #endif glMatrixMode(GL_MODELVIEW); glEnable(GL_DEPTH_TEST); // If we have multi-configs, show their origin onscreen. for (k = 0; k < gMultiConfigCount; k++) { showMErr[k] = FALSE; if (gMultiConfigs[k]->prevF != 0) { arglCameraViewRH((const ARdouble (*)[4])gMultiConfigs[k]->trans, m, 1.0); #ifdef ARDOUBLE_IS_FLOAT glLoadMatrixf(m); #else glLoadMatrixd(m); #endif drawAxes(); #ifdef ARDOUBLE_IS_FLOAT for (i = 0; i < 16; i++) m0[i] = (GLdouble)m[i]; for (i = 0; i < 16; i++) p0[i] = (GLdouble)p[i]; if (gluProject(0, 0, 0, m0, p0, gViewport, &winX, &winY, &winZ) == GL_TRUE) #else if (gluProject(0, 0, 0, m, p, gViewport, &winX, &winY, &winZ) == GL_TRUE) #endif { showMErr[k] = TRUE; MX[k] = winX; MY[k] = winY; } } } // for k } // Any 2D overlays go here. glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, (GLdouble)windowWidth, 0, (GLdouble)windowHeight, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); arGetPatternDetectionMode(gARHandle, &pattDetectMode); arGetMatrixCodeType(gARHandle, &matrixCodeType); // For all markers, draw onscreen position. // Colour based on cutoffPhase. glLoadIdentity(); glVertexPointer(2, GL_FLOAT, 0, vertices); glEnableClientState(GL_VERTEX_ARRAY); glLineWidth(2.0f); for (j = 0; j < gARHandle->marker_num; j++) { glColor3ubv(cutoffPhaseColours[gARHandle->markerInfo[j].cutoffPhase].colour); for (i = 0; i < 5; i++) { int dir = gARHandle->markerInfo[j].dir; vertices[i][0] = (float)gARHandle->markerInfo[j].vertex[(i + 4 - dir) % 4][0] * (float)windowWidth / (float)gARHandle->xsize; vertices[i][1] = ((float)gARHandle->ysize - (float)gARHandle->markerInfo[j].vertex[(i + 4 - dir) % 4][1]) * (float)windowHeight / (float)gARHandle->ysize; } vertices[i][0] = (float)gARHandle->markerInfo[j].pos[0] * (float)windowWidth / (float)gARHandle->xsize; vertices[i][1] = ((float)gARHandle->ysize - (float)gARHandle->markerInfo[j].pos[1]) * (float)windowHeight / (float)gARHandle->ysize; glDrawArrays(GL_LINE_STRIP, 0, 6); // For markers that have been identified, draw the ID number. if (gARHandle->markerInfo[j].id >= 0) { glColor3ub(255, 0, 0); if (matrixCodeType == AR_MATRIX_CODE_GLOBAL_ID && (pattDetectMode == AR_MATRIX_CODE_DETECTION || pattDetectMode == AR_TEMPLATE_MATCHING_COLOR_AND_MATRIX || pattDetectMode == AR_TEMPLATE_MATCHING_MONO_AND_MATRIX)) snprintf(text, sizeof(text), "%llu (err=%d)", gARHandle->markerInfo[j].globalID, gARHandle->markerInfo[j].errorCorrected); else snprintf(text, sizeof(text), "%d", gARHandle->markerInfo[j].id); print(text, (float)gARHandle->markerInfo[j].pos[0] * (float)windowWidth / (float)gARHandle->xsize, ((float)gARHandle->ysize - (float)gARHandle->markerInfo[j].pos[1]) * (float)windowHeight / (float)gARHandle->ysize, 0, 0); } } glDisableClientState(GL_VERTEX_ARRAY); // For matrix mode, draw the pattern image of the largest marker. if (pattDetectMode == AR_MATRIX_CODE_DETECTION || pattDetectMode == AR_TEMPLATE_MATCHING_COLOR_AND_MATRIX || pattDetectMode == AR_TEMPLATE_MATCHING_MONO_AND_MATRIX) { int area = 0, biggestMarker = -1; for (j = 0; j < gARHandle->marker_num; j++) if (gARHandle->markerInfo[j].area > area) { area = gARHandle->markerInfo[j].area; biggestMarker = j; } if (area >= AR_AREA_MIN) { int imageProcMode; ARdouble pattRatio; ARUint8 ext_patt[AR_PATT_SIZE2_MAX * AR_PATT_SIZE2_MAX * 3]; // Holds unwarped pattern extracted from image. int size; int zoom = 4; ARdouble vertexUpright[4][2]; // Reorder vertices based on dir. for (i = 0; i < 4; i++) { int dir = gARHandle->markerInfo[biggestMarker].dir; vertexUpright[i][0] = gARHandle->markerInfo[biggestMarker].vertex[(i + 4 - dir) % 4][0]; vertexUpright[i][1] = gARHandle->markerInfo[biggestMarker].vertex[(i + 4 - dir) % 4][1]; } arGetImageProcMode(gARHandle, &imageProcMode); arGetPattRatio(gARHandle, &pattRatio); if (matrixCodeType == AR_MATRIX_CODE_GLOBAL_ID) { size = 14; arPattGetImage2(imageProcMode, AR_MATRIX_CODE_DETECTION, size, size * AR_PATT_SAMPLE_FACTOR2, gARTImage, gARHandle->xsize, gARHandle->ysize, gARHandle->arPixelFormat, &gCparamLT->paramLTf, vertexUpright, (ARdouble)14 / (ARdouble)(14 + 2), ext_patt); } else { size = matrixCodeType & AR_MATRIX_CODE_TYPE_SIZE_MASK; arPattGetImage2(imageProcMode, AR_MATRIX_CODE_DETECTION, size, size * AR_PATT_SAMPLE_FACTOR2, gARTImage, gARHandle->xsize, gARHandle->ysize, gARHandle->arPixelFormat, &gCparamLT->paramLTf, vertexUpright, pattRatio, ext_patt); } glRasterPos2f((float)(windowWidth - size * zoom) - 4.0f, (float)(size * zoom) + 4.0f); glPixelZoom((float)zoom, (float)-zoom); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glDrawPixels(size, size, GL_LUMINANCE, GL_UNSIGNED_BYTE, ext_patt); glPixelZoom(1.0f, 1.0f); } } // Draw error value for multimarker pose. for (k = 0; k < gMultiConfigCount; k++) { if (showMErr[k]) { snprintf(text, sizeof(text), "err=%0.3f", gMultiErrs[k]); print(text, MX[k], MY[k], 0, 0); } } // // Draw help text and mode. // glLoadIdentity(); if (gShowMode) { printMode(); } if (gShowHelp) { if (gShowHelp == 1) { printHelpKeys(); } else if (gShowHelp == 2) { bw = 0.0f; for (i = 0; i < AR_MARKER_INFO_CUTOFF_PHASE_DESCRIPTION_COUNT; i++) { w = (float)glutBitmapLength(GLUT_BITMAP_HELVETICA_10, (unsigned char*)arMarkerInfoCutoffPhaseDescriptions[cutoffPhaseColours[i].cutoffPhase]); if (w > bw) bw = w; } bw += 12.0f; // Space for color block. bh = AR_MARKER_INFO_CUTOFF_PHASE_DESCRIPTION_COUNT * 10.0f /* character height */ + (AR_MARKER_INFO_CUTOFF_PHASE_DESCRIPTION_COUNT - 1) * 2.0f /* line spacing */; drawBackground(bw, bh, 2.0f, 2.0f); // Draw the colour block and text, line by line. for (i = 0; i < AR_MARKER_INFO_CUTOFF_PHASE_DESCRIPTION_COUNT; i++) { for (j = 0; j < 300; j += 3) { pixels[j] = cutoffPhaseColours[i].colour[0]; pixels[j + 1] = cutoffPhaseColours[i].colour[1]; pixels[j + 2] = cutoffPhaseColours[i].colour[2]; } glRasterPos2f(2.0f, (AR_MARKER_INFO_CUTOFF_PHASE_DESCRIPTION_COUNT - 1 - i) * 12.0f + 2.0f); glPixelZoom(1.0f, 1.0f); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glDrawPixels(10, 10, GL_RGB, GL_UNSIGNED_BYTE, pixels); print(arMarkerInfoCutoffPhaseDescriptions[cutoffPhaseColours[i].cutoffPhase], 14.0f, (AR_MARKER_INFO_CUTOFF_PHASE_DESCRIPTION_COUNT - 1 - i) * 12.0f + 2.0f, 0, 0); } } } glutSwapBuffers(); }
void renderOpenGLFromImageData(OpenGL* ogl, char* pixels, int width, int height, int rowstride, int destWidth, int destHeight, int upx, int upy, int upwidth, int upheight) { if (ogl == NULL) { printf("null OGL\n"); return; } //return; configure_window(ogl, destWidth, destHeight); gdk_gl_drawable_gl_begin(ogl->drawable, ogl->context); if (1) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBindTexture(GL_TEXTURE_2D, ogl->screentexid); if (1||!ogl->screentexloaded) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rowstride / 3, height, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); ogl->screentexloaded = 1; } else { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, height-upy, rowstride / 3, upheight, GL_RGB, GL_UNSIGNED_BYTE, pixels); } /* glPushMatrix(); glScalef((double)destWidth / (rowstride/3), (double)destHeight / height, 1); glBegin(GL_QUADS); glTexCoord2i((double)upx / (rowstride/3), (double)upy / height); glVertex2f(upx, upy); glTexCoord2i((double)(upx + upwidth) / (rowstride/3), (double)upy / height); glVertex2f(upx + upwidth, upy); glTexCoord2i((double)(upx + upwidth) / (rowstride/3), (double)(upy + upheight) / height); glVertex2f(upx + upwidth, upy + upheight); glTexCoord2i((double)upx / (rowstride/3), (double)(upy + upheight) / height); glVertex2f(upx, upy + upheight); */ if (0 && ogl->displaylist) { glPushMatrix(); glScalef((double)destWidth/width, (double)destHeight/height, 1); glCallList(ogl->displaylist); glPopMatrix(); } else { //int list = glGenLists(1); // ogl->displaylist = list; //glNewList(ogl->displaylist, GL_COMPILE_AND_EXECUTE); glPushMatrix(); glScalef((double)destWidth, (double)destHeight, 1); glClearColor(0, 0, 0, 1); //glClear(GL_COLOR_BUFFER_BIT); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2i(0, 0); glVertex2f(0, 0); glTexCoord2i(1, 0); glVertex2f(1, 0); glTexCoord2i(1, 1); glVertex2f(1, 1); glTexCoord2i(0, 1); glVertex2f(0, 1); glEnd(); glPopMatrix(); //glEndList(); } } else if (0) { glPixelZoom((double) destWidth / width, (double) -destHeight / height); glClearColor(0, 0, 0, 1); //glClear(GL_COLOR_BUFFER_BIT); //glRasterPos2i(0, 0); //glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); glPixelStorei(GL_UNPACK_ROW_LENGTH, width); glPixelStorei(GL_UNPACK_SKIP_ROWS, upy); glPixelStorei(GL_UNPACK_SKIP_PIXELS, upx); glRasterPos2i((double) upx * destWidth / height, (double) upy * destHeight / height); glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); } else if (0) { int r, c; //glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_TEXTURE_2D); float scalex = (double) destWidth / width; float scaley = (double) destHeight / height; glPointSize((scalex + scaley) / 2); glBegin(GL_POINTS); glColor3b(0, 0, 0); int last = 0; for (r = 0; r < height; r++) { unsigned char* ptr = (unsigned char *) pixels + (r * rowstride); for (c = 0; c < width; c++) { int color = (ptr[0] << 16) | (ptr[1] << 8) | (ptr[2]); if (color != last) glColor3b(ptr[0], ptr[1], ptr[2]); glVertex3f(c * scalex, r * scaley, 0.0); ptr += 3; last = color; } } glEnd(); } else if (1) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(2, GL_SHORT, 0, ogl->vertices); glColorPointer(3, GL_UNSIGNED_BYTE, 0, pixels); glPushMatrix(); glScalef((double)destWidth / width, (double)destHeight / height, 1); glDrawElements(GL_QUADS, 49152 * 4, GL_UNSIGNED_SHORT, ogl->indices); glPopMatrix(); } //if (gdk_gl_drawable_is_double_buffered (ogl->drawable)) gdk_gl_drawable_swap_buffers(ogl->drawable); gdk_gl_drawable_gl_end(ogl->drawable); }
PsychError SCREENPutImage(void) { PsychRectType windowRect,positionRect; int ix, iy, numPlanes, bitsPerColor, matrixRedIndex, matrixGreenIndex, matrixBlueIndex, matrixAlphaIndex, matrixGrayIndex; int inputM, inputN, inputP, positionRectWidth, positionRectHeight; PsychWindowRecordType *windowRecord; unsigned char *inputMatrixByte; double *inputMatrixDouble; GLuint *compactMat, matrixGrayValue, matrixRedValue, matrixGreenValue, matrixBlueValue, matrixAlphaValue, compactPixelValue; PsychArgFormatType inputMatrixType; GLfloat xZoom=1, yZoom=-1; //all sub functions should have these two lines PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //cap the number of inputs PsychErrorExit(PsychCapNumInputArgs(4)); //The maximum number of inputs PsychErrorExit(PsychCapNumOutputArgs(0)); //The maximum number of outputs //get the image matrix inputMatrixType=PsychGetArgType(2); switch(inputMatrixType){ case PsychArgType_none : case PsychArgType_default: PsychErrorExitMsg(PsychError_user, "imageArray argument required"); break; case PsychArgType_uint8 : PsychAllocInUnsignedByteMatArg(2, TRUE, &inputM, &inputN, &inputP, &inputMatrixByte); break; case PsychArgType_double : PsychAllocInDoubleMatArg(2, TRUE, &inputM, &inputN, &inputP, &inputMatrixDouble); break; default : PsychErrorExitMsg(PsychError_user, "imageArray must be uint8 or double type"); break; } //get the window and get the rect and stuff PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); numPlanes=PsychGetNumPlanesFromWindowRecord(windowRecord); bitsPerColor=PsychGetColorSizeFromWindowRecord(windowRecord); PsychGetRectFromWindowRecord(windowRect, windowRecord); if(PsychCopyInRectArg(3, FALSE, positionRect)){ positionRectWidth=(int)PsychGetWidthFromRect(positionRect); positionRectHeight=(int)PsychGetHeightFromRect(positionRect); if(inputP != 1 && inputP != 3 && inputP != 4) PsychErrorExitMsg(PsychError_user, "Third dimension of image matrix must be 1, 3, or 4"); if( positionRectWidth != inputN || positionRectHeight != inputM){ //calculate the zoom factor xZoom=(GLfloat)positionRectWidth/(GLfloat)inputN; yZoom=-((GLfloat)positionRectHeight/(GLfloat)inputM); } }else{ positionRect[kPsychLeft]=0; positionRect[kPsychTop]=0; positionRect[kPsychRight]=inputN; positionRect[kPsychBottom]=inputM; PsychCenterRect(positionRect, windowRect, positionRect); //This should be centered } //put up the image if(numPlanes==1){ //screen planes, not image matrix planes. PsychErrorExitMsg(PsychError_unimplemented, "Put Image does not yet support indexed mode"); //remember to test here for inputP==3 because that would be wrong. }else if(numPlanes==4){ compactMat=(GLuint *)mxMalloc(sizeof(GLuint) * inputN * inputM); for(ix=0;ix<inputN;ix++){ for(iy=0;iy<inputM;iy++){ if(inputP==1){ matrixGrayIndex=PsychIndexElementFrom3DArray(inputM, inputN, 1, iy, ix, 0); if(inputMatrixType==PsychArgType_uint8) matrixGrayValue=(GLuint)inputMatrixByte[matrixGrayIndex]; else //inputMatrixType==PsychArgType_double matrixGrayValue=(GLuint)inputMatrixDouble[matrixGrayIndex]; compactPixelValue=((matrixGrayValue<<8 | matrixGrayValue)<<8 | matrixGrayValue)<<8 | 255; compactMat[iy*inputN+ix]=compactPixelValue; }else if(inputP==3){ matrixRedIndex=PsychIndexElementFrom3DArray(inputM, inputN, 3, iy, ix, 0); matrixGreenIndex=PsychIndexElementFrom3DArray(inputM, inputN, 3, iy, ix, 1); matrixBlueIndex=PsychIndexElementFrom3DArray(inputM, inputN, 3, iy, ix, 2); if(inputMatrixType==PsychArgType_uint8){ matrixRedValue=(GLuint)inputMatrixByte[matrixRedIndex]; matrixGreenValue=(GLuint)inputMatrixByte[matrixGreenIndex]; matrixBlueValue=(GLuint)inputMatrixByte[matrixBlueIndex]; matrixAlphaValue=(GLuint)255; }else{ matrixRedValue=(GLuint)inputMatrixDouble[matrixRedIndex]; matrixGreenValue=(GLuint)inputMatrixDouble[matrixGreenIndex]; matrixBlueValue=(GLuint)inputMatrixDouble[matrixBlueIndex]; matrixAlphaValue=(GLuint)255; } compactPixelValue= ((matrixRedValue<<8 | matrixGreenValue )<<8 | matrixBlueValue)<<8 | matrixAlphaValue; compactMat[iy*inputN+ix]=compactPixelValue; }else if(inputP==4){ matrixRedIndex=PsychIndexElementFrom3DArray(inputM, inputN, 3, iy, ix, 0); matrixGreenIndex=PsychIndexElementFrom3DArray(inputM, inputN, 3, iy, ix, 1); matrixBlueIndex=PsychIndexElementFrom3DArray(inputM, inputN, 3, iy, ix, 2); matrixAlphaIndex=PsychIndexElementFrom3DArray(inputM, inputN, 3, iy, ix, 3); if(inputMatrixType==PsychArgType_uint8){ matrixRedValue=(GLuint)inputMatrixByte[matrixRedIndex]; matrixGreenValue=(GLuint)inputMatrixByte[matrixGreenIndex]; matrixBlueValue=(GLuint)inputMatrixByte[matrixBlueIndex]; matrixAlphaValue=(GLuint)inputMatrixByte[matrixAlphaIndex]; }else{ matrixRedValue=(GLuint)inputMatrixDouble[matrixRedIndex]; matrixGreenValue=(GLuint)inputMatrixDouble[matrixGreenIndex]; matrixBlueValue=(GLuint)inputMatrixDouble[matrixBlueIndex]; matrixAlphaValue=(GLuint)inputMatrixDouble[matrixAlphaIndex]; } compactPixelValue= ((matrixRedValue<<8 | matrixGreenValue )<<8 | matrixBlueValue)<<8 | matrixAlphaValue; compactMat[iy*inputN+ix]=compactPixelValue; } } } PsychSetGLContext(windowRecord); PsychUpdateAlphaBlendingFactorLazily(windowRecord); glRasterPos2i((GLint)(positionRect[kPsychLeft]), (GLint)(positionRect[kPsychTop])); PsychTestForGLErrors(); glPixelStorei(GL_UNPACK_ALIGNMENT, (GLint)(sizeof(GLuint))); //4 PsychTestForGLErrors(); glPixelZoom(xZoom,yZoom); PsychTestForGLErrors(); glDrawPixels(inputN, inputM, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, compactMat); free((void *)compactMat); PsychTestForGLErrors(); PsychFlushGL(windowRecord); //OS X: This does nothing if we are multi buffered, otherwise it glFlushes PsychTestForGLErrors(); }else if(numPlanes==3) PsychErrorExitMsg(PsychError_unimplemented, "PutImage found hardware without an alpha channel."); return(PsychError_none); }
void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dx, int dy, int width, int height, bool transparent, const DeviceDrawParams &draw_params) { assert(rgba.type == MEM_PIXELS); mem_copy_from(rgba, y, w, h, rgba.memory_elements_size(1)); if(transparent) { glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } glColor3f(1.0f, 1.0f, 1.0f); if(rgba.data_type == TYPE_HALF) { /* for multi devices, this assumes the inefficient method that we allocate * all pixels on the device even though we only render to a subset */ GLhalf *host_pointer = (GLhalf*)rgba.host_pointer; float vbuffer[16], *basep; float *vp = NULL; host_pointer += 4*y*w; /* draw half float texture, GLSL shader for display transform assumed to be bound */ GLuint texid; glGenTextures(1, &texid); glBindTexture(GL_TEXTURE_2D, texid); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, h, 0, GL_RGBA, GL_HALF_FLOAT, host_pointer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_TEXTURE_2D); if(draw_params.bind_display_space_shader_cb) { draw_params.bind_display_space_shader_cb(); } if(GLEW_VERSION_1_5) { if(!vertex_buffer) glGenBuffers(1, &vertex_buffer); glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */ glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW); vp = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); basep = NULL; } else { basep = vbuffer; vp = vbuffer; } if(vp) { /* texture coordinate - vertex pair */ vp[0] = 0.0f; vp[1] = 0.0f; vp[2] = dx; vp[3] = dy; vp[4] = 1.0f; vp[5] = 0.0f; vp[6] = (float)width + dx; vp[7] = dy; vp[8] = 1.0f; vp[9] = 1.0f; vp[10] = (float)width + dx; vp[11] = (float)height + dy; vp[12] = 0.0f; vp[13] = 1.0f; vp[14] = dx; vp[15] = (float)height + dy; if(vertex_buffer) glUnmapBuffer(GL_ARRAY_BUFFER); } glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), basep); glVertexPointer(2, GL_FLOAT, 4 * sizeof(float), ((char *)basep) + 2 * sizeof(float)); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); if(vertex_buffer) { glBindBuffer(GL_ARRAY_BUFFER, 0); } if(draw_params.unbind_display_space_shader_cb) { draw_params.unbind_display_space_shader_cb(); } glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); glDeleteTextures(1, &texid); } else { /* fallback for old graphics cards that don't support GLSL, half float, * and non-power-of-two textures */ glPixelZoom((float)width/(float)w, (float)height/(float)h); glRasterPos2f(dx, dy); uint8_t *pixels = (uint8_t*)rgba.host_pointer; pixels += 4*y*w; glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glRasterPos2f(0.0f, 0.0f); glPixelZoom(1.0f, 1.0f); } if(transparent) glDisable(GL_BLEND); }
static void HandleDisplay(void) { const WebPDecBuffer* const pic = kParams.pic; const WebPIterator* const iter = &kParams.frameiter; GLfloat xoff, yoff; if (pic == NULL) return; glPushMatrix(); glPixelZoom(1, -1); xoff = (GLfloat)(2. * iter->x_offset / kParams.canvas_width); yoff = (GLfloat)(2. * iter->y_offset / kParams.canvas_height); glRasterPos2f(-1.f + xoff, 1.f - yoff); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4); if (kParams.prev_frame.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { // TODO(later): these offsets and those above should factor in window size. // they will be incorrect if the window is resized. // glScissor() takes window coordinates (0,0 at bottom left). const int window_x = kParams.prev_frame.x_offset; const int window_y = kParams.canvas_height - kParams.prev_frame.y_offset - kParams.prev_frame.height; glEnable(GL_SCISSOR_TEST); // Only updated the requested area, not the whole canvas. glScissor(window_x, window_y, kParams.prev_frame.width, kParams.prev_frame.height); glClear(GL_COLOR_BUFFER_BIT); // use clear color DrawCheckerBoard(); glDisable(GL_SCISSOR_TEST); } kParams.prev_frame.width = iter->width; kParams.prev_frame.height = iter->height; kParams.prev_frame.x_offset = iter->x_offset; kParams.prev_frame.y_offset = iter->y_offset; kParams.prev_frame.dispose_method = iter->dispose_method; glDrawPixels(pic->width, pic->height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)pic->u.RGBA.rgba); if (kParams.print_info) { char tmp[32]; glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glRasterPos2f(-0.95f, 0.90f); PrintString(kParams.file_name); snprintf(tmp, sizeof(tmp), "Dimension:%d x %d", pic->width, pic->height); glColor4f(0.90f, 0.0f, 0.90f, 1.0f); glRasterPos2f(-0.95f, 0.80f); PrintString(tmp); if (iter->x_offset != 0 || iter->y_offset != 0) { snprintf(tmp, sizeof(tmp), " (offset:%d,%d)", iter->x_offset, iter->y_offset); glRasterPos2f(-0.95f, 0.70f); PrintString(tmp); } } glPopMatrix(); glFlush(); }
void ocpnDC::DrawBitmap( const wxBitmap &bitmap, wxCoord x, wxCoord y, bool usemask ) { #ifdef ocpnUSE_GLES // Do not attempt to do anything with glDrawPixels if using opengles return; #endif wxBitmap bmp; if( x < 0 || y < 0 ) { int dx = ( x < 0 ? -x : 0 ); int dy = ( y < 0 ? -y : 0 ); int w = bitmap.GetWidth() - dx; int h = bitmap.GetHeight() - dy; /* picture is out of viewport */ if( w <= 0 || h <= 0 ) return; wxBitmap newBitmap = bitmap.GetSubBitmap( wxRect( dx, dy, w, h ) ); x += dx; y += dy; bmp = newBitmap; } else { bmp = bitmap; } if( dc ) dc->DrawBitmap( bmp, x, y, usemask ); #ifdef ocpnUSE_GL else { wxImage image = bmp.ConvertToImage(); int w = image.GetWidth(), h = image.GetHeight(); if( usemask ) { unsigned char *d = image.GetData(); unsigned char *a = image.GetAlpha(); unsigned char mr, mg, mb; if( !image.GetOrFindMaskColour( &mr, &mg, &mb ) && !a ) printf( "trying to use mask to draw a bitmap without alpha or mask\n" ); unsigned char *e = new unsigned char[4 * w * h]; if(e && d){ for( int y = 0; y < h; y++ ) for( int x = 0; x < w; x++ ) { unsigned char r, g, b; int off = ( y * image.GetWidth() + x ); r = d[off * 3 + 0]; g = d[off * 3 + 1]; b = d[off * 3 + 2]; e[off * 4 + 0] = r; e[off * 4 + 1] = g; e[off * 4 + 2] = b; e[off * 4 + 3] = a ? a[off] : ( ( r == mr ) && ( g == mg ) && ( b == mb ) ? 0 : 255 ); } } glColor4f( 1, 1, 1, 1 ); GLDrawBlendData( x, y, w, h, GL_RGBA, e ); delete[] ( e ); } else { glRasterPos2i( x, y ); glPixelZoom( 1, -1 ); /* draw data from top to bottom */ if(image.GetData()) glDrawPixels( w, h, GL_RGB, GL_UNSIGNED_BYTE, image.GetData() ); glPixelZoom( 1, 1 ); } } #endif }
void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int width, int height, bool transparent, const DeviceDrawParams &draw_params) { pixels_copy_from(rgba, y, w, h); if(transparent) { glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } glColor3f(1.0f, 1.0f, 1.0f); if(rgba.data_type == TYPE_HALF) { /* for multi devices, this assumes the inefficient method that we allocate * all pixels on the device even though we only render to a subset */ GLhalf *data_pointer = (GLhalf*)rgba.data_pointer; data_pointer += 4*y*w; /* draw half float texture, GLSL shader for display transform assumed to be bound */ GLuint texid; glGenTextures(1, &texid); glBindTexture(GL_TEXTURE_2D, texid); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, h, 0, GL_RGBA, GL_HALF_FLOAT, data_pointer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_TEXTURE_2D); if(draw_params.bind_display_space_shader_cb) { draw_params.bind_display_space_shader_cb(); } glPushMatrix(); glTranslatef(0.0f, (float)dy, 0.0f); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex2f((float)width, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex2f((float)width, (float)height); glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, (float)height); glEnd(); glPopMatrix(); if(draw_params.unbind_display_space_shader_cb) { draw_params.unbind_display_space_shader_cb(); } glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); glDeleteTextures(1, &texid); } else { /* fallback for old graphics cards that don't support GLSL, half float, * and non-power-of-two textures */ glPixelZoom((float)width/(float)w, (float)height/(float)h); glRasterPos2f(0, dy); uint8_t *pixels = (uint8_t*)rgba.data_pointer; pixels += 4*y*w; glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glRasterPos2f(0.0f, 0.0f); glPixelZoom(1.0f, 1.0f); } if(transparent) glDisable(GL_BLEND); }
void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY) { unsigned char *uc_rect = (unsigned char *) rect; float *f_rect = (float *)rect; float xzoom = glaGetOneFloat(GL_ZOOM_X), yzoom = glaGetOneFloat(GL_ZOOM_Y); int ltexid = glaGetOneInteger(GL_TEXTURE_2D); int lrowlength = glaGetOneInteger(GL_UNPACK_ROW_LENGTH); int subpart_x, subpart_y, tex_w, tex_h; int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y; int texid = get_cached_work_texture(&tex_w, &tex_h); int components; /* Specify the color outside this function, and tex will modulate it. * This is useful for changing alpha without using glPixelTransferf() */ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w); glBindTexture(GL_TEXTURE_2D, texid); /* don't want nasty border artifacts */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter); #ifdef __APPLE__ /* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */ glPixelZoom(1.f, 1.f); #endif /* setup seamless 2=on, 0=off */ seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0; offset_x = tex_w - seamless; offset_y = tex_h - seamless; nsubparts_x = (img_w + (offset_x - 1)) / (offset_x); nsubparts_y = (img_h + (offset_y - 1)) / (offset_y); if (format == GL_RGBA) components = 4; else if (format == GL_RGB) components = 3; else if (format == GL_LUMINANCE) components = 1; else { BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled"); return; } if (type == GL_FLOAT) { /* need to set internal format to higher range float */ /* NOTE: this could fail on some drivers, like mesa, * but currently this code is only used by color * management stuff which already checks on whether * it's possible to use GL_RGBA16F_ARB */ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, tex_w, tex_h, 0, format, GL_FLOAT, NULL); } else { /* switch to 8bit RGBA for byte buffer */ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL); } for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) { for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) { int remainder_x = img_w - subpart_x * offset_x; int remainder_y = img_h - subpart_y * offset_y; int subpart_w = (remainder_x < tex_w) ? remainder_x : tex_w; int subpart_h = (remainder_y < tex_h) ? remainder_y : tex_h; int offset_left = (seamless && subpart_x != 0) ? 1 : 0; int offset_bot = (seamless && subpart_y != 0) ? 1 : 0; int offset_right = (seamless && remainder_x > tex_w) ? 1 : 0; int offset_top = (seamless && remainder_y > tex_h) ? 1 : 0; float rast_x = x + subpart_x * offset_x * xzoom; float rast_y = y + subpart_y * offset_y * yzoom; /* check if we already got these because we always get 2 more when doing seamless*/ if (subpart_w <= seamless || subpart_h <= seamless) continue; if (type == GL_FLOAT) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]); /* add an extra border of pixels so linear looks ok at edges of full image. */ if (subpart_w < tex_w) glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); if (subpart_h < tex_h) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w && subpart_h < tex_h) glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); } else { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w) glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); if (subpart_h < tex_h) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w && subpart_h < tex_h) glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); } glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h); glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom); glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h); glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom); glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h); glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY); glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h); glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY); glEnd(); glDisable(GL_TEXTURE_2D); } } glBindTexture(GL_TEXTURE_2D, ltexid); glPixelStorei(GL_UNPACK_ROW_LENGTH, lrowlength); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifdef __APPLE__ /* workaround for os x 10.5/10.6 driver bug (above) */ glPixelZoom(xzoom, yzoom); #endif }
///////////////////////////////////////////////////////// // Render // void GEMglPixelZoom :: render(GemState *state) { glPixelZoom (xfactor, yfactor); }
void reshape(int w, int h) { glPixelZoom((float)w/COLS, (float)h/ROWS); }
void CamField::_ComputePixPerDeg( float width, float height, bool display ) { float camWidth, camHeight; float camFovx = 40.0; if(display && _image) { camWidth = _image->width; camHeight = _image->height; } else { camWidth = 800; camHeight = 600; } float camAspectRatio = camWidth/camHeight; float windowAspectRatio = (float)width/(float)height; float fieldWidth, fieldHeight; float temp; (camAspectRatio > windowAspectRatio) ? temp = (float)width/camWidth : temp = (float)height/camHeight; fieldWidth = camWidth*temp; fieldHeight = camHeight*temp; pixPerDeg = fieldHeight/camFovx; if(display && _image) { #if DISPLAY_METHOD == 1 glRasterPos2i((width-fieldWidth)/2., (height+fieldHeight)/2.-1); glPixelZoom(temp, -temp); glDrawPixels(camWidth, camHeight, GL_RGB, GL_UNSIGNED_BYTE, _image->imageData); glPixelZoom(1, 1); #elif DISPLAY_METHOD == 2 if(ready) { gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, camWidth, camHeight, GL_RGB, GL_UNSIGNED_BYTE, _image->imageData); } #elif DISPLAY_METHOD == 3 if(ready) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); gluScaleImage(GL_RGB, camWidth, camHeight, GL_UNSIGNED_BYTE, _image->imageData, 512, 512, GL_UNSIGNED_BYTE, _image->imageData); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, _image->imageData); ready = 0; } #endif #if (DISPLAY_METHOD == 2) || (DISPLAY_METHOD == 3) glEnable(GL_TEXTURE_2D); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslated(width/2, height/2, 0); glBegin(GL_QUADS); glTexCoord2f(0.0f, 1.0f); glVertex2f(-fieldWidth/2, -fieldHeight/2); glTexCoord2f(1.0f, 1.0f); glVertex2f(fieldWidth/2, -fieldHeight/2); glTexCoord2f(1.0f, 0.0f); glVertex2f(fieldWidth/2, fieldHeight/2); glTexCoord2f(0.0f, 0.0f); glVertex2f(-fieldWidth/2, fieldHeight/2); glEnd(); glDisable(GL_TEXTURE_2D); #endif } }
PsychError SCREENWaitBlanking(void) { PsychWindowRecordType *windowRecord; int waitFrames, framesWaited; double tvbl, ifi; long screenwidth, screenheight; int vbl_startline, beampos, lastline; psych_uint64 vblCount, vblRefCount; CGDirectDisplayID cgDisplayID; GLint read_buffer, draw_buffer; // All subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumInputArgs(2)); //The maximum number of inputs PsychErrorExit(PsychRequireNumInputArgs(1)); //The required number of inputs PsychErrorExit(PsychCapNumOutputArgs(1)); //The maximum number of outputs // Get the window record from the window record argument and get info from the window record PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); if(!PsychIsOnscreenWindow(windowRecord)) PsychErrorExitMsg(PsychError_user, "Tried to call 'WaitBlanking' on something else than an onscreen window!"); // Get the number of frames to wait: waitFrames = 0; PsychCopyInIntegerArg(2, FALSE, &waitFrames); // We default to wait at least one interval if no argument supplied: waitFrames = (waitFrames < 1) ? 1 : waitFrames; // Enable this windowRecords framebuffer as current drawingtarget: // This is needed to make sure that Offscreen windows work propely. PsychSetDrawingTarget(windowRecord); // Retrieve display handle for beamposition queries: PsychGetCGDisplayIDFromScreenNumber(&cgDisplayID, windowRecord->screenNumber); // Retrieve final vbl_startline, aka physical height of the display in pixels: PsychGetScreenSize(windowRecord->screenNumber, &screenwidth, &screenheight); vbl_startline = (int) screenheight; // Query duration of a monitor refresh interval: We try to use the measured interval, // but fallback of the nominal value reported by the operating system if necessary: if ((ifi = windowRecord->VideoRefreshInterval)<=0) { if (PsychGetNominalFramerate(windowRecord->screenNumber) > 0) { // Valid nominal framerate returned by OS: Calculate nominal IFI from it. ifi = 1.0 / ((double) PsychGetNominalFramerate(windowRecord->screenNumber)); } else { // No reasonable value available! We fallback to an assumed 60 Hz refresh... ifi = 1.0 / 60.0; } } // Query vblcount to test if this method works correctly: PsychOSGetVBLTimeAndCount(windowRecord, &vblRefCount); // Check if beamposition queries are supported by this OS and working properly: if (-1 != PsychGetDisplayBeamPosition(cgDisplayID, windowRecord->screenNumber) && windowRecord->VBL_Endline >= 0) { // Beamposition queries supported and fine. We can wait for VBL without bufferswap-tricks: // This is the OS-X way of doing things. We query the rasterbeamposition and compare it // to the known values for the VBL area. If we enter VBL, we take a timestamp and return - // or wait for the next VBL if waitFrames>0 // Query current beamposition when entering WaitBlanking: beampos = PsychGetDisplayBeamPosition(cgDisplayID, windowRecord->screenNumber); // Are we in VBL when entering WaitBlanking? If so, we should wait for one additional frame, // because by definition, WaitBlanking should always wait for at least one monitor refresh // interval... if ((beampos<=windowRecord->VBL_Endline) && (beampos>=vbl_startline)) waitFrames++; while(waitFrames > 0) { // Enough time for a sleep? If the beam is far away from VBL area, we try to sleep to // yield some CPU time to other processes in the system -- we are nice citizens ;) beampos = PsychGetDisplayBeamPosition(cgDisplayID, windowRecord->screenNumber); while (( ((float)(vbl_startline - beampos)) / (float) windowRecord->VBL_Endline * ifi) > 0.003) { // At least 3 milliseconds left until retrace. We sleep for 1 millisecond. PsychWaitIntervalSeconds(0.001); beampos = PsychGetDisplayBeamPosition(cgDisplayID, windowRecord->screenNumber); } // Less than 3 ms away from retrace. Busy-Wait for retrace... lastline = PsychGetDisplayBeamPosition(cgDisplayID, windowRecord->screenNumber); beampos = lastline; while ((beampos < vbl_startline) && (beampos >= lastline)) { lastline = beampos; beampos = (long) PsychGetDisplayBeamPosition(cgDisplayID, windowRecord->screenNumber); } // Retrace! Take system timestamp of VBL onset: PsychGetAdjustedPrecisionTimerSeconds(&tvbl); // If this wasn't the last frame to wait, we need to wait for end of retrace before // repeating the loop, because otherwise we would detect the same VBL and skip frames. // If it is the last frame, we skip it and return as quickly as possible to save the // Matlab script some extra Millisecond for drawing... if (waitFrames>1) { beampos = vbl_startline; while ((beampos<=windowRecord->VBL_Endline) && (beampos>=vbl_startline)) { beampos = PsychGetDisplayBeamPosition(cgDisplayID, windowRecord->screenNumber); }; } // Done with this refresh interval... // Decrement remaining number of frames to wait: waitFrames--; } } else if (vblRefCount > 0) { // Display beamposition queries unsupported, but vblank count queries seem to work. Try those. // Should work on Linux and OS/X: while(waitFrames > 0) { vblCount = vblRefCount; // Wait for next vblank counter increment - aka start of next frame (its vblank): while (vblCount == vblRefCount) { // Requery: PsychOSGetVBLTimeAndCount(windowRecord, &vblCount); // Yield at least 100 usecs. This is accurate as this code-path // only executes on OS/X and Linux, never on Windows (as of 01/06/2011): PsychYieldIntervalSeconds(0.000100); } vblRefCount = vblCount; // Done with this refresh interval... // Decrement remaining number of frames to wait: waitFrames--; } } else { // Other methods unsupported. We use the doublebuffer swap method of waiting for retrace. // // Working principle: On each frame, we first copy the content of the (user visible) frontbuffer into the backbuffer. // Then we ask the OS to perform a front-backbuffer swap on next vertical retrace and go to sleep via glFinish() et al. // until the OS signals swap-completion. This way PTB's/Matlabs execution will stall until VBL, when swap happens and // we get woken up. We repeat this procedure 'waitFrames' times, then we take a high precision timestamp and exit the // Waitblanking loop. As backbuffer and frontbuffer are identical (due to the copy) at swap time, the visual display // won't change at all for the subject. // This method should work reliably, but it has one drawback: A random wakeup delay (scheduling jitter) is added after // retrace has been entered, so Waitblanking returns only after the beam has left retrace state on older hardware. // This means a bit less time (1 ms?) for stimulus drawing on Windows than on OS-X where Waitblanking returns faster. // Child protection: if (windowRecord->windowType != kPsychDoubleBufferOnscreen) { PsychErrorExitMsg(PsychError_internal, "WaitBlanking tried to perform swap-waiting on a single buffered window!"); } // Setup buffers for front->back copy op: // Backup old read- writebuffer assignments: glGetIntegerv(GL_READ_BUFFER, &read_buffer); glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer); // Set read- and writebuffer properly: glReadBuffer(GL_FRONT); glDrawBuffer(GL_BACK); // Reset viewport to full-screen default: glViewport(0, 0, screenwidth, screenheight); glScissor(0, 0, screenwidth, screenheight); // Reset color buffer writemask to "All enabled": glColorMask(TRUE, TRUE, TRUE, TRUE); glDisable(GL_BLEND); glPixelZoom(1,1); // Disable draw shader: PsychSetShader(windowRecord, 0); // Swap-Waiting loop for 'waitFrames' frames: while(waitFrames > 0) { // Copy current content of front buffer into backbuffer: glRasterPos2i(0, screenheight); glCopyPixels(0, 0, screenwidth, screenheight, GL_COLOR); // Ok, front- and backbuffer are now identical, so a bufferswap // will be a visual no-op. // Enable beamsyncing of bufferswaps to VBL: PsychOSSetVBLSyncLevel(windowRecord, 1); // Trigger bufferswap in sync with retrace: PsychOSFlipWindowBuffers(windowRecord); // Wait for swap-completion, aka beginning of VBL: PsychWaitPixelSyncToken(windowRecord); // VBL happened - Take system timestamp: PsychGetAdjustedPrecisionTimerSeconds(&tvbl); // This code-chunk is an alternate way of syncing, only used for debugging: if (false) { // Disable beamsyncing of bufferswaps to VBL: PsychOSSetVBLSyncLevel(windowRecord, 0); // Swap buffers immediately without vsync: PsychOSFlipWindowBuffers(windowRecord); } // Decrement remaining number of frames to wait: waitFrames--; } // Do it again... // Enable beamsyncing of bufferswaps to VBL: PsychOSSetVBLSyncLevel(windowRecord, 1); // Restore assignment of read- writebuffers and such: glEnable(GL_BLEND); glReadBuffer(read_buffer); glDrawBuffer(draw_buffer); // Done with Windows waitblanking... } // Compute number of frames waited: It is timestamp of return of this waitblanking minus // timestamp of return of last waitblanking, divided by duration of a monitor refresh // interval, mathematically rounded to an integral number: framesWaited = (int) (((tvbl - windowRecord->time_at_last_vbl) / ifi) + 0.5f); // Update timestamp for next invocation of Waitblanking: windowRecord->time_at_last_vbl = tvbl; // Return optional number of frames waited: PsychCopyOutDoubleArg(1, FALSE, (double) framesWaited); // Done. return(PsychError_none); }
/////////////////////////////////////////////////////////////////////// // Called to draw scene void RenderScene(void) { GLint i; // Looping variable GLint iViewport[4]; // Viewport GLint iLargest; // Largest histogram value static GLubyte invertTable[256][3];// Inverted color table // Do a black and white scaling static GLfloat lumMat[16] = { 0.30f, 0.30f, 0.30f, 0.0f, 0.59f, 0.59f, 0.59f, 0.0f, 0.11f, 0.11f, 0.11f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; static GLfloat mSharpen[3][3] = { // Sharpen convolution kernel {0.0f, -1.0f, 0.0f}, {-1.0f, 5.0f, -1.0f }, {0.0f, -1.0f, 0.0f }}; static GLfloat mEmboss[3][3] = { // Emboss convolution kernel { 2.0f, 0.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }, { 0.0f, 0.0f, -1.0f }}; static GLint histoGram[256]; // Storeage for histogram statistics // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT); // Current Raster Position always at bottom left hand corner of window glRasterPos2i(0, 0); glGetIntegerv(GL_VIEWPORT, iViewport); glPixelZoom((GLfloat) iViewport[2] / (GLfloat)iWidth, (GLfloat) iViewport[3] / (GLfloat)iHeight); if(bHistogram == GL_TRUE) // Collect Historgram data { // We are collecting luminance data, use our conversion formula // instead of OpenGL's (which just adds color components together) glMatrixMode(GL_COLOR); glLoadMatrixf(lumMat); glMatrixMode(GL_MODELVIEW); // Start collecting histogram data, 256 luminance values glHistogram(GL_HISTOGRAM, 256, GL_LUMINANCE, GL_FALSE); glEnable(GL_HISTOGRAM); } // Do image operation, depending on rendermode index switch(iRenderMode) { case 5: // Sharpen image glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_RGB, 3, 3, GL_LUMINANCE, GL_FLOAT, mSharpen); glEnable(GL_CONVOLUTION_2D); break; case 4: // Emboss image glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_RGB, 3, 3, GL_LUMINANCE, GL_FLOAT, mEmboss); glEnable(GL_CONVOLUTION_2D); glMatrixMode(GL_COLOR); glLoadMatrixf(lumMat); glMatrixMode(GL_MODELVIEW); break; case 3: // Invert Image for(i = 0; i < 255; i++) { invertTable[i][0] = (GLubyte)(255 - i); invertTable[i][1] = (GLubyte)(255 - i); invertTable[i][2] = (GLubyte)(255 - i); } glColorTable(GL_COLOR_TABLE, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, invertTable); glEnable(GL_COLOR_TABLE); break; case 2: // Brighten Image glMatrixMode(GL_COLOR); glScalef(1.25f, 1.25f, 1.25f); glMatrixMode(GL_MODELVIEW); break; case 1: // Just do a plain old image copy default: // This line intentially left blank break; } // Do the pixel draw glDrawPixels(iWidth, iHeight, eFormat, GL_UNSIGNED_BYTE, pImage); // Fetch and draw histogram? if(bHistogram == GL_TRUE) { // Read histogram data into buffer glGetHistogram(GL_HISTOGRAM, GL_TRUE, GL_LUMINANCE, GL_INT, histoGram); // Find largest value for scaling graph down iLargest = 0; for(i = 0; i < 255; i++) if(iLargest < histoGram[i]) iLargest = histoGram[i]; // White lines glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_LINE_STRIP); for(i = 0; i < 255; i++) glVertex2f((GLfloat)i, (GLfloat)histoGram[i] / (GLfloat) iLargest * 128.0f); glEnd(); bHistogram = GL_FALSE; glDisable(GL_HISTOGRAM); } // Reset everyting to default glMatrixMode(GL_COLOR); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glDisable(GL_CONVOLUTION_2D); glDisable(GL_COLOR_TABLE); // Show our hard work... glutSwapBuffers(); }