void COpenGL::Render(SSurface Src) { SSurface Dst; RECT dstRect; unsigned int newFilterScale; GLenum error; if(!initDone) return; //create a new draw surface if the filter scale changes //at least factor 2 so we can display unscaled hi-res images newFilterScale = max(2,max(GetFilterScale(GUI.ScaleHiRes),GetFilterScale(GUI.Scale))); if(newFilterScale!=filterScale) { ChangeDrawSurfaceSize(newFilterScale); } if(pboFunctionsLoaded) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, drawBuffer); Dst.Surface = (unsigned char *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER,GL_WRITE_ONLY); } else { Dst.Surface = noPboBuffer; } Dst.Height = quadTextureSize; Dst.Width = quadTextureSize; Dst.Pitch = quadTextureSize * 2; RenderMethod (Src, Dst, &dstRect); if(!Settings.AutoDisplayMessages) { WinSetCustomDisplaySurface((void *)Dst.Surface, Dst.Pitch/2, dstRect.right-dstRect.left, dstRect.bottom-dstRect.top, GetFilterScale(CurrentScale)); S9xDisplayMessages ((uint16*)Dst.Surface, Dst.Pitch/2, dstRect.right-dstRect.left, dstRect.bottom-dstRect.top, GetFilterScale(CurrentScale)); } if(pboFunctionsLoaded) glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); if(afterRenderHeight != dstRect.bottom || afterRenderWidth != dstRect.right) { afterRenderHeight = dstRect.bottom; afterRenderWidth = dstRect.right; ChangeRenderSize(0,0); } glBindTexture(GL_TEXTURE_2D,drawTexture); glPixelStorei(GL_UNPACK_ROW_LENGTH, quadTextureSize); glTexSubImage2D (GL_TEXTURE_2D,0,0,0,dstRect.right-dstRect.left,dstRect.bottom-dstRect.top,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,pboFunctionsLoaded?0:noPboBuffer); if(pboFunctionsLoaded) glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); if (shader_type != OGL_SHADER_NONE) { if(shader_type == OGL_SHADER_GLSL) { GLint location; float inputSize[2] = { (float)afterRenderWidth, (float)afterRenderHeight }; RECT windowSize; GetClientRect(hWnd,&windowSize); float outputSize[2] = {(float)(GUI.Stretch?windowSize.right:afterRenderWidth), (float)(GUI.Stretch?windowSize.bottom:afterRenderHeight) }; float textureSize[2] = { (float)quadTextureSize, (float)quadTextureSize }; float frameCnt = (float)++frameCount; location = glGetUniformLocation (shaderProgram, "rubyInputSize"); glUniform2fv (location, 1, inputSize); location = glGetUniformLocation (shaderProgram, "rubyOutputSize"); glUniform2fv (location, 1, outputSize); location = glGetUniformLocation (shaderProgram, "rubyTextureSize"); glUniform2fv (location, 1, textureSize); } else if(shader_type == OGL_SHADER_CG) { xySize inputSize = { (float)afterRenderWidth, (float)afterRenderHeight }; RECT windowSize, displayRect; GetClientRect(hWnd,&windowSize); xySize xywindowSize = { (double)windowSize.right, (double)windowSize.bottom }; //Get maximum rect respecting AR setting displayRect=CalculateDisplayRect(windowSize.right,windowSize.bottom,windowSize.right,windowSize.bottom); xySize viewportSize = { (double)(displayRect.right - displayRect.left), (double)(displayRect.bottom - displayRect.top) }; xySize textureSize = { (double)quadTextureSize, (double)quadTextureSize }; cgShader->Render(drawTexture, textureSize, inputSize, viewportSize, xywindowSize); } } if(GUI.BilinearFilter) { glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } else { glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays (GL_QUADS, 0, 4); glFlush(); SwapBuffers(hDC); }
static int GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch) { GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata; Uint8 *blob = NULL; Uint8 *src; int srcPitch; int y; GLES2_ActivateRenderer(renderer); /* Bail out if we're supposed to update an empty rectangle */ if (rect->w <= 0 || rect->h <= 0) return 0; /* Reformat the texture data into a tightly packed array */ srcPitch = rect->w * SDL_BYTESPERPIXEL(texture->format); src = (Uint8 *)pixels; if (pitch != srcPitch) { blob = (Uint8 *)SDL_malloc(srcPitch * rect->h); if (!blob) { SDL_OutOfMemory(); return -1; } src = blob; for (y = 0; y < rect->h; ++y) { SDL_memcpy(src, pixels, srcPitch); src += srcPitch; pixels = (Uint8 *)pixels + pitch; } src = blob; } /* Create a texture subimage with the supplied data */ glGetError(); glActiveTexture(GL_TEXTURE0); glBindTexture(tdata->texture_type, tdata->texture); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexSubImage2D(tdata->texture_type, 0, rect->x, rect->y, rect->w, rect->h, tdata->pixel_format, tdata->pixel_type, src); if (blob) { SDL_free(blob); } if (glGetError() != GL_NO_ERROR) { SDL_SetError("Failed to update texture"); return -1; } return 0; }
void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) { rctf rect; if ((!g->width) || (!g->height)) return; if (g->build_tex == 0) { GlyphCacheBLF *gc = font->glyph_cache; if (font->max_tex_size == -1) glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->max_tex_size); if (gc->cur_tex == -1) { blf_glyph_cache_texture(font, gc); gc->x_offs = gc->pad; gc->y_offs = 0; } if (gc->x_offs > (gc->p2_width - gc->max_glyph_width)) { gc->x_offs = gc->pad; gc->y_offs += gc->max_glyph_height; if (gc->y_offs > (gc->p2_height - gc->max_glyph_height)) { gc->y_offs = 0; blf_glyph_cache_texture(font, gc); } } g->tex = gc->textures[gc->cur_tex]; g->xoff = gc->x_offs; g->yoff = gc->y_offs; /* prevent glTexSubImage2D from failing if the character * asks for pixels out of bounds, this tends only to happen * with very small sizes (5px high or less) */ if (UNLIKELY((g->xoff + g->width) > gc->p2_width)) { g->width -= (g->xoff + g->width) - gc->p2_width; BLI_assert(g->width > 0); } if (UNLIKELY((g->yoff + g->height) > gc->p2_height)) { g->height -= (g->yoff + g->height) - gc->p2_height; BLI_assert(g->height > 0); } glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBindTexture(GL_TEXTURE_2D, g->tex); glTexSubImage2D(GL_TEXTURE_2D, 0, g->xoff, g->yoff, g->width, g->height, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap); glPopClientAttrib(); g->uv[0][0] = ((float)g->xoff) / ((float)gc->p2_width); g->uv[0][1] = ((float)g->yoff) / ((float)gc->p2_height); g->uv[1][0] = ((float)(g->xoff + g->width)) / ((float)gc->p2_width); g->uv[1][1] = ((float)(g->yoff + g->height)) / ((float)gc->p2_height); /* update the x offset for the next glyph. */ gc->x_offs += (int)(BLI_rctf_size_x(&g->box) + gc->pad); gc->rem_glyphs--; g->build_tex = 1; } blf_glyph_calc_rect(&rect, g, x, y); if (font->flags & BLF_CLIPPING) { /* intentionally check clipping without shadow offset */ rctf rect_test = rect; BLI_rctf_translate(&rect_test, font->pos[0], font->pos[1]); if (!BLI_rctf_inside_rctf(&font->clip_rec, &rect_test)) { return; } } if (font->tex_bind_state != g->tex) { glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = g->tex)); } if (font->flags & BLF_SHADOW) { rctf rect_ofs; blf_glyph_calc_rect(&rect_ofs, g, x + font->shadow_x, y + font->shadow_y); switch (font->shadow) { case 3: blf_texture3_draw(font->shadow_col, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax); break; case 5: blf_texture5_draw(font->shadow_col, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax); break; default: glColor4fv(font->shadow_col); blf_texture_draw(g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax); break; } glColor4fv(font->orig_col); } switch (font->blur) { case 3: blf_texture3_draw(font->orig_col, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax); break; case 5: blf_texture5_draw(font->orig_col, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax); break; default: blf_texture_draw(g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax); break; } return; }
bool Texture2D::SetData(unsigned level, int x, int y, int width, int height, const void* data) { if (!object_ || !graphics_) { LOGERROR("No texture created, can not set data"); return false; } if (!data) { LOGERROR("Null source for setting data"); return false; } if (level >= levels_) { LOGERROR("Illegal mip level for setting data"); return false; } if (graphics_->IsDeviceLost()) { LOGWARNING("Texture data assignment while device is lost"); dataPending_ = true; return true; } if (IsCompressed()) { x &= ~3; y &= ~3; } int levelWidth = GetLevelWidth(level); int levelHeight = GetLevelHeight(level); if (x < 0 || x + width > levelWidth || y < 0 || y + height > levelHeight || width <= 0 || height <= 0) { LOGERROR("Illegal dimensions for setting data"); return false; } bool wholeLevel = x == 0 && y == 0 && width == levelWidth && height == levelHeight; // Use Direct3D convention with the vertical coordinates ie. 0 is top y = levelHeight - (y + height); graphics_->SetTextureForUpdate(this); unsigned format = GetSRGB() ? GetSRGBFormat(format_) : format_; if (!IsCompressed()) { if (wholeLevel) glTexImage2D(target_, level, format, width, height, 0, GetExternalFormat(format_), GetDataType(format_), data); else glTexSubImage2D(target_, level, x, y, width, height, GetExternalFormat(format_), GetDataType(format_), data); } else { if (wholeLevel) glCompressedTexImage2D(target_, level, format, width, height, 0, GetDataSize(width, height), data); else glCompressedTexSubImage2D(target_, level, x, y, width, height, format, GetDataSize(width, height), data); } graphics_->SetTexture(0, 0); return true; }
enum piglit_result test_tex_image(void *null) { bool pass = true; int break_pbo_cow, break_tex_cow; /* cow = copy on write */ int use_unpack, use_pack; GLuint unpack_pb[1]; GLuint pack_pb[1]; GLenum pack = GL_PIXEL_PACK_BUFFER_ARB; GLenum unpack = GL_PIXEL_UNPACK_BUFFER_ARB; GLfloat t1[TEXTURE_SIZE]; GLfloat t2[TEXTURE_SIZE]; GLfloat *pbo_mem = NULL; int i, j; GLfloat green[3] = { 1.0, 1.0, 0.0 }; GLfloat black[3] = { 0.0, 0.0, 0.0 }; GLfloat buf[WINDOW_SIZE]; GLfloat exp_tex[TEXTURE_SIZE]; GLfloat exp_win[WINDOW_SIZE]; GLfloat tolerance[4]; piglit_compute_probe_tolerance(GL_RGB, tolerance); glBindBufferARB(unpack, 0); glBindBufferARB(pack, 0); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); for (use_pack = 0; use_pack < 2; use_pack++) { for (use_unpack = 0; use_unpack < 2; use_unpack++) { for (break_pbo_cow = 0; break_pbo_cow < use_unpack + 1; break_pbo_cow++) { for (break_tex_cow = 0; break_tex_cow < use_unpack + 1; break_tex_cow++) { if (use_unpack) { glGenBuffersARB(1, unpack_pb); glBindBufferARB(unpack, unpack_pb[0]); glBufferDataARB(unpack, TEXTURE_SIZE * sizeof(GLfloat), NULL, GL_STREAM_DRAW); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (use_unpack) { pbo_mem = (GLfloat *) glMapBufferARB(unpack, GL_WRITE_ONLY); } else { pbo_mem = t1; } for (i = 0; i < TEXTURE_SIZE/3; i++) { pbo_mem[3 * i] = 1.0; pbo_mem[3 * i + 1] = 1.0; pbo_mem[3 * i + 2] = 0.0; } if (use_unpack) { glUnmapBufferARB(unpack); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_RGB, GL_FLOAT, NULL); glBindBufferARB(unpack, 0); } else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_RGB, GL_FLOAT, pbo_mem); if (use_unpack && break_pbo_cow) { glBindBufferARB(unpack, unpack_pb[0]); pbo_mem = (GLfloat *) glMapBufferARB( unpack, GL_WRITE_ONLY); for (i = 0; i < TEXTURE_SIZE; i++) pbo_mem[i] = 0.2; glUnmapBufferARB(unpack); glBindBufferARB(unpack, 0); } if (use_unpack && break_tex_cow) { GLfloat temp[3]; for (i = 0; i < 3; i++) temp[i] = 0.8; glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGB, GL_FLOAT, temp); } /* Check PBO's content */ if (use_unpack) { glBindBufferARB(unpack, unpack_pb[0]); pbo_mem = (GLfloat *) glMapBuffer(unpack, GL_READ_ONLY); if (break_pbo_cow) { for (i = 0; i < TEXTURE_SIZE; i++) if (fabsf(pbo_mem[i] - 0.2f) > tolerance[0]) { REPORT_FAILURE ("PBO modified by someone else, " "there must be something wrong"); return PIGLIT_FAIL; } } glUnmapBufferARB(unpack); glBindBufferARB(unpack, 0); } /* Read texture back */ if (use_pack) { glGenBuffersARB(1, pack_pb); glBindBufferARB(pack, pack_pb[0]); glBufferDataARB(pack, TEXTURE_SIZE * sizeof(GLfloat), NULL, GL_STREAM_DRAW); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_FLOAT, NULL); pbo_mem = (GLfloat *) glMapBufferARB(pack, GL_READ_ONLY); } else { glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_FLOAT, t2); pbo_mem = t2; } /* Check texture image */ for (i = 0; i < TEXTURE_SIZE/3; i++) { int idx = i * 3; if (i == 0 && break_tex_cow && use_unpack) { exp_tex[idx + 0] = 0.8; exp_tex[idx + 1] = 0.8; exp_tex[idx + 2] = 0.8; } else { exp_tex[idx + 0] = 1.0; exp_tex[idx + 1] = 1.0; exp_tex[idx + 2] = 0.0; } } pass &= piglit_compare_images_color(0, 0, TEXSIZE, TEXSIZE, 3, tolerance, exp_tex, pbo_mem); if (use_pack) { glUnmapBufferARB(pack); glBindBufferARB(pack, 0); glDeleteBuffersARB(1, pack_pb); } if (use_unpack) { glDeleteBuffersARB(1, unpack_pb); } glEnable(GL_TEXTURE_2D); glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(TEXSIZE, 0); glTexCoord2f(1, 1); glVertex2f(TEXSIZE, TEXSIZE); glTexCoord2f(0, 1); glVertex2f(0, TEXSIZE); glEnd(); glDisable(GL_TEXTURE_2D); glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, buf); for (j = 0; j < WINSIZE; j++) { for (i = 0; i < WINSIZE; i++) { int idx = (j * WINSIZE + i) * 3; if (i == 0 && j == 0 && break_tex_cow && use_unpack) { exp_win[idx + 0] = 0.8; exp_win[idx + 1] = 0.8; exp_win[idx + 2] = 0.8; } else if (i < TEXSIZE && j < TEXSIZE) { exp_win[idx + 0] = green[0]; exp_win[idx + 1] = green[1]; exp_win[idx + 2] = green[2]; } else { exp_win[idx + 0] = black[0]; exp_win[idx + 1] = black[1]; exp_win[idx + 2] = black[2]; } } } pass &= piglit_compare_images_color(0, 0, WINSIZE, WINSIZE, 3, tolerance, exp_win, buf); } } } } return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
void VideoSource::draw() { // to draw the border/text/common stuff, also calls animateValues RectangleBase::draw(); // replicate the invisible -> don't draw thing here; above needs to be // called since it does the animation if ( borderColor.A < 0.01f ) return; // set up our position glPushMatrix(); // dumb hack here to prevent z-fighting on orbit glTranslatef( x, y, z + 0.05f ); glRotatef( xAngle, 1.0, 0.0, 0.0 ); glRotatef( yAngle, 0.0, 1.0, 0.0 ); glRotatef( zAngle, 0.0, 0.0, 1.0 ); //glDepthMask( GL_FALSE ); //glEnable( GL_POLYGON_OFFSET_FILL ); //glDepthRange ( 0.0, 0.9 ); //glPolygonOffset( 1.0, 1.0 ); float s = 1.0; float t = 1.0; // if the texture id hasn't been initialized yet, this must be the // first draw call init = (texid == 0); // allocate the buffer if it's the first time or if it's been resized if ( init || vwidth != videoSink->getImageWidth() || vheight != videoSink->getImageHeight() ) { resizeBuffer(); } s = (float)vwidth/(float)tex_width; //if ( videoSink->getImageFormat() == VIDEO_FORMAT_YUV420 ) // t = (float)(3*vheight/2)/(float)tex_height; //else t = (float)vheight/(float)tex_height; // X & Y distances from center to edge float Xdist = aspect*scaleX/2; float Ydist = scaleY/2; glBindTexture( GL_TEXTURE_2D, texid ); glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glPixelStorei( GL_UNPACK_ROW_LENGTH, vwidth ); // only do this texture stuff if rendering is enabled if ( enableRendering ) { videoSink->lockImage(); // only bother doing a texture push if there's a new frame if ( videoSink->haveNewFrameAvailable() ) { if ( videoSink->getImageFormat() == VIDEO_FORMAT_RGB24 ) { glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, vwidth, vheight, GL_RGB, GL_UNSIGNED_BYTE, videoSink->getImageData() ); } // if we're doing yuv420, do the texture mapping for all 3 channels // so the shader can properly work its magic else if ( videoSink->getImageFormat() == VIDEO_FORMAT_YUV420 ) { // experimental single-push method /*glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, vwidth, 3*vheight/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, videoSink->getImageData() );*/ // 3 pushes separate glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, vwidth, vheight, GL_LUMINANCE, GL_UNSIGNED_BYTE, videoSink->getImageData() ); // now map the U & V to the bottom chunk of the image // each is 1/4 of the size of the Y (half width, half height) glPixelStorei(GL_UNPACK_ROW_LENGTH, vwidth/2); glTexSubImage2D( GL_TEXTURE_2D, 0, 0, vheight, vwidth/2, vheight/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, (GLubyte*)videoSink->getImageData() + (vwidth*vheight) ); glTexSubImage2D( GL_TEXTURE_2D, 0, vwidth/2, vheight, vwidth/2, vheight/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, (GLubyte*)videoSink->getImageData() + 5*(vwidth*vheight)/4 ); } } videoSink->unlockImage(); } // draw video texture, regardless of whether we just pushed something // new or not if ( GLUtil::getInstance()->areShadersAvailable() ) { glUseProgram( GLUtil::getInstance()->getYUV420Program() ); glUniform1f( GLUtil::getInstance()->getYUV420xOffsetID(), s ); glUniform1f( GLUtil::getInstance()->getYUV420yOffsetID(), t ); if ( useAlpha ) { glUniform1f( GLUtil::getInstance()->getYUV420alphaID(), borderColor.A ); } } // use alpha of border color for video if set if ( useAlpha ) { glColor4f( 1.0f, 1.0f, 1.0f, borderColor.A ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } else { glColor3f( 1.0f, 1.0f, 1.0f ); } glEnable( GL_TEXTURE_2D ); glBegin( GL_QUADS ); // now draw the actual quad that has the texture on it // size of the video in world space will be equivalent to getWidth x // getHeight, which is the same as (aspect*scaleX) x scaleY glTexCoord2f( 0.0, 0.0 ); glVertex3f( -Xdist, -Ydist, 0.0 ); glTexCoord2f( 0.0, t ); glVertex3f( -Xdist, Ydist, 0.0 ); glTexCoord2f( s, t ); glVertex3f( Xdist, Ydist, 0.0 ); glTexCoord2f( s, 0.0 ); glVertex3f( Xdist, -Ydist, 0.0 ); glEnd(); glDisable( GL_TEXTURE_2D ); if ( GLUtil::getInstance()->areShadersAvailable() ) glUseProgram( 0 ); if ( vwidth == 0 || vheight == 0 ) { glPushMatrix(); glTranslatef( -(getWidth()*0.275f), getHeight()*0.3f, 0.0f ); float scaleFactor = getTextScale(); glScalef( scaleFactor, scaleFactor, scaleFactor ); std::string waitingMessage( "Waiting for video..." ); GLUtil::getInstance()->getMainFont()->Render( waitingMessage.c_str() ); glPopMatrix(); } // draw a basic X in the top-left corner for signifying that rendering is // disabled, differentiating between muting and just having the texture // push disabled via the color if ( !enableRendering ) { float dist = getHeight() * 0.15f; glBegin( GL_LINES ); glLineWidth( 3.0f ); glColor4f( secondaryColor.R, secondaryColor.G, secondaryColor.B, secondaryColor.A ); glVertex3f( -Xdist, Ydist - dist, 0.0f ); glVertex3f( -Xdist + dist, Ydist, 0.0f ); glVertex3f( -Xdist, Ydist, 0.0f ); glVertex3f( -Xdist + dist, Ydist - dist, 0.0f ); glEnd(); } if ( altAddress.compare( "" ) != 0 ) { float scaleFactor = getTextScale() * 1.25f; float offset = getHeight() * 0.01f; glPushMatrix(); glTranslatef( -Xdist + offset, -Ydist + offset, 0.0f ); glScalef( scaleFactor, scaleFactor, scaleFactor ); glColor4f( 0.55f, 0.55f, 0.95f, borderColor.A + 0.1f ); std::string plus = "+HD"; GLUtil::getInstance()->getMainFont()->Render( plus.c_str() ); glPopMatrix(); /*glBegin( GL_QUADS ); float dist = getHeight() * 0.15f; glColor4f( 0.4f, 0.4f, 0.8f, borderColor.A - 0.3f ); glVertex3f( Xdist - dist, -Ydist + ( dist / 3.0f ), 0.0f ); glVertex3f( Xdist - dist, -Ydist + ( 2.0f * dist / 3.0f ), 0.0f ); glVertex3f( Xdist, -Ydist + ( 2.0f * dist / 3.0f ), 0.0f ); glVertex3f( Xdist, -Ydist + ( dist / 3.0f ), 0.0f ); glVertex3f( Xdist - ( 2.0f * dist / 3.0f ), -Ydist, 0.0f ); glVertex3f( Xdist - ( 2.0f * dist / 3.0f ), -Ydist + dist, 0.0f ); glVertex3f( Xdist - ( dist / 3.0f ), -Ydist + dist, 0.0f ); glVertex3f( Xdist - ( dist / 3.0f ), -Ydist, 0.0f ); glEnd();*/ } // see above if ( useAlpha ) { glDisable( GL_BLEND ); } glPopMatrix(); //glDisable( GL_POLYGON_OFFSET_FILL ); }
void display() { // clear screen glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); // use the browser texture glBindTexture( GL_TEXTURE_2D, mAppTexture ); // needs to be updated? mMediaSource->update(); if ( mMediaSource->isDirty() ) { // grab the page const unsigned char* pixels = mMediaSource->getPixels(); if ( pixels ) { // write them into the texture glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, mMediaSource->getWidth(), mMediaSource->getHeight(), mMediaSource->getPixelFormat(), GL_UNSIGNED_BYTE, pixels ); // acknowledge we saw media was dirty and updated mMediaSource->ackDirty(); }; }; // scale the texture so that it fits the screen GLfloat texture_scale_x = ( GLfloat )mMediaSource->getWidth() / ( GLfloat )mAppTextureWidth; GLfloat texture_scale_y = ( GLfloat )mMediaSource->getHeight() / ( GLfloat )mAppTextureHeight; // draw the single quad full screen (orthographic) glMatrixMode( GL_TEXTURE ); glPushMatrix(); glScalef( texture_scale_x, texture_scale_y, 1.0f ); glEnable( GL_TEXTURE_2D ); glColor3f( 1.0f, 1.0f, 1.0f ); glBegin( GL_QUADS ); glTexCoord2f( 1.0f, 1.0f ); glVertex2d( mAppWindowWidth, 0 ); glTexCoord2f( 0.0f, 1.0f ); glVertex2d( 0, 0 ); glTexCoord2f( 0.0f, 0.0f ); glVertex2d( 0, mAppWindowHeight ); glTexCoord2f( 1.0f, .0f ); glVertex2d( mAppWindowWidth, mAppWindowHeight ); glEnd(); glMatrixMode( GL_TEXTURE ); glPopMatrix(); glutSwapBuffers(); };
void ODPoint::DrawGL( PlugIn_ViewPort &pivp ) { if( !m_bIsVisible ) return; // Optimization, especially apparent on tracks in normal cases if( m_IconName == _T("empty") && !m_bShowName && !m_bPtIsSelected ) return; if(m_wpBBox.GetValid() && pivp.chart_scale == m_wpBBox_chart_scale && pivp.rotation == m_wpBBox_rotation) { } wxPoint r; wxRect hilitebox; unsigned char transparency = 150; GetCanvasPixLL( &g_VP, &r, m_lat, m_lon ); // Substitue icon? wxBitmap *pbm; if( ( m_bIsActive ) && ( m_IconName != _T("mob") ) ) pbm = g_pODPointMan->GetIconBitmap( _T ( "activepoint" ) ); else pbm = m_pbmIcon; int sx2 = pbm->GetWidth() / 2; int sy2 = pbm->GetHeight() / 2; // Calculate the mark drawing extents wxRect r1( r.x - sx2, r.y - sy2, sx2 * 2, sy2 * 2 ); // the bitmap extents float l_fIconScaleFactor = GetOCPNChartScaleFactor_Plugin(); wxRect r3 = r1; if( m_bShowName ) { if( !m_pMarkFont ) { m_pMarkFont = GetOCPNScaledFont_PlugIn( wxT( "Marks" ) ); m_FontColor = GetFontColour_PlugIn( wxS( "Marks" ) ); CalculateNameExtents(); } if( m_pMarkFont ) { wxRect r2( r.x + (m_NameLocationOffsetX * l_fIconScaleFactor), r.y + (m_NameLocationOffsetY * l_fIconScaleFactor), m_NameExtents.x, m_NameExtents.y ); r3.Union( r2 ); } } hilitebox = r3; hilitebox.x -= r.x; hilitebox.y -= r.y; float radius; if( IsTouchInterface_PlugIn() ){ hilitebox.Inflate( 20 ); radius = 20.0f; } else{ hilitebox.Inflate( 4 ); radius = 4.0f; } /* update bounding box */ if(!m_wpBBox.GetValid() || pivp.chart_scale != m_wpBBox_chart_scale || pivp.rotation != m_wpBBox_rotation) { double lat1, lon1, lat2, lon2; wxPoint wxpoint; wxpoint.x = r.x+hilitebox.x; wxpoint.y = r.y + hilitebox.height; GetCanvasLLPix( &pivp, wxpoint, &lat1, &lon1 ); wxpoint.x = r.x + hilitebox.x + hilitebox.width; wxpoint.y = r.y + hilitebox.y; GetCanvasLLPix( &pivp, wxpoint, &lat2, &lon2 ); if(lon1 > lon2) m_wpBBox.Set(lat1, lon1, lat2, lon2+360); else m_wpBBox.Set(lat1, lon1, lat2, lon2); m_wpBBox_chart_scale = pivp.chart_scale; m_wpBBox_rotation = pivp.rotation; } ODDC dc; // Highlite any selected point if( m_bPtIsSelected || m_bIsBeingEdited ) { wxColour hi_colour; if( m_bPointPropertiesBlink || m_bPathManagerBlink ){ wxPen *pen = g_pPathMan->GetActiveODPointPen(); hi_colour = pen->GetColour(); } else{ GetGlobalColor( wxS( "YELO1" ), &hi_colour ); } g_ocpn_draw_pi->AlphaBlending( dc, r.x + hilitebox.x, r.y + hilitebox.y, hilitebox.width, hilitebox.height, radius, hi_colour, transparency ); } bool bDrawHL = false; if( (m_bPointPropertiesBlink || m_bPathManagerBlink) && ( g_ocpn_draw_pi->nBlinkerTick & 1 ) ) bDrawHL = true; if( ( !bDrawHL ) && ( NULL != m_pbmIcon ) ) { int glw, glh; unsigned int IconTexture = g_pODPointMan->GetIconTexture( pbm, glw, glh ); glBindTexture(GL_TEXTURE_2D, IconTexture); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glColor3f(1, 1, 1); float l_ChartScaleFactorExp = GetOCPNChartScaleFactor_Plugin(); float w = r1.width * l_ChartScaleFactorExp; float h = r1.height * l_ChartScaleFactorExp; float x = r.x - w/2; float y = r.y - h/2; float u = (float)r1.width/glw, v = (float)r1.height/glh; glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(x, y); glTexCoord2f(u, 0); glVertex2f(x+w, y); glTexCoord2f(u, v); glVertex2f(x+w, y+h); glTexCoord2f(0, v); glVertex2f(x, y+h); glEnd(); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); } if( m_bShowName && m_pMarkFont ) { int w = m_NameExtents.x, h = m_NameExtents.y; if(!m_iTextTexture && w && h) { wxBitmap tbm(w, h); /* render text on dc */ wxMemoryDC dc; dc.SelectObject( tbm ); dc.SetBackground( wxBrush( *wxBLACK ) ); dc.Clear(); dc.SetFont( *m_pMarkFont ); dc.SetTextForeground( *wxWHITE ); dc.DrawText( m_ODPointName, 0, 0); dc.SelectObject( wxNullBitmap ); /* make alpha texture for text */ wxImage image = tbm.ConvertToImage(); unsigned char *d = image.GetData(); unsigned char *e = new unsigned char[w * h]; if(d && e){ for( int p = 0; p < w*h; p++) e[p] = d[3*p + 0]; } /* create texture for rendered text */ glGenTextures(1, &m_iTextTexture); glBindTexture(GL_TEXTURE_2D, m_iTextTexture); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); m_iTextTextureWidth = NextPow2(w); m_iTextTextureHeight = NextPow2(h); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_iTextTextureWidth, m_iTextTextureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, e); delete [] e; } if(m_iTextTexture) { /* draw texture with text */ glBindTexture(GL_TEXTURE_2D, m_iTextTexture); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor3ub(m_FontColor.Red(), m_FontColor.Green(), m_FontColor.Blue()); int x = r.x + (m_NameLocationOffsetX * l_fIconScaleFactor), y = r.y + (m_NameLocationOffsetY * l_fIconScaleFactor); float u = (float)w/m_iTextTextureWidth, v = (float)h/m_iTextTextureHeight; glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(x, y); glTexCoord2f(u, 0); glVertex2f(x+w, y); glTexCoord2f(u, v); glVertex2f(x+w, y+h); glTexCoord2f(0, v); glVertex2f(x, y+h); glEnd(); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); } } // Draw ODPoint range rings if activated if( m_iODPointRangeRingsNumber && m_bShowODPointRangeRings ) { double factor = 1.00; if( m_iODPointRangeRingsStepUnits == 1 ) // nautical miles factor = 1 / 1.852; factor *= m_fODPointRangeRingsStep; double tlat, tlon; wxPoint r1; ll_gc_ll( m_lat, m_lon, 0, factor, &tlat, &tlon ); GetCanvasPixLL( &g_VP, &r1, tlat, tlon); double lpp = sqrt( pow( (double) (r.x - r1.x), 2) + pow( (double) (r.y - r1.y), 2 ) ); int pix_radius = (int) lpp; wxPen ppPen1( m_wxcODPointRangeRingsSchemeColour, m_iRangeRingWidth, m_iRangeRingStyle ); wxBrush saveBrush = dc.GetBrush(); wxPen savePen = dc.GetPen(); dc.SetPen( ppPen1 ); dc.SetBrush( wxBrush( m_wxcODPointRangeRingsSchemeColour, wxBRUSHSTYLE_TRANSPARENT ) ); dc.SetGLStipple(); for( int i = 1; i <= m_iODPointRangeRingsNumber; i++ ) dc.StrokeCircle( r.x, r.y, i * pix_radius ); glDisable( GL_LINE_STIPPLE ); dc.SetPen( savePen ); dc.SetBrush( saveBrush ); } if( m_bPointPropertiesBlink || m_bPathManagerBlink ) g_blink_rect = CurrentRect_in_DC; // also save for global blinker // This will be useful for fast icon redraws CurrentRect_in_DC.x = r.x + hilitebox.x; CurrentRect_in_DC.y = r.y + hilitebox.y; CurrentRect_in_DC.width = hilitebox.width; CurrentRect_in_DC.height = hilitebox.height; if( m_bPointPropertiesBlink || m_bPathManagerBlink ) g_blink_rect = CurrentRect_in_DC; // also save for global blinker }
cairo_status_t _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, cairo_image_surface_t *src, int src_x, int src_y, int width, int height, int dst_x, int dst_y) { GLenum internal_format, format, type; cairo_bool_t has_alpha, needs_swap; cairo_image_surface_t *clone = NULL; cairo_gl_context_t *ctx; int cpp; cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; status = _cairo_gl_context_acquire (dst->base.device, &ctx); if (unlikely (status)) return status; if (! _cairo_gl_get_image_format_and_type (ctx->gl_flavor, src->pixman_format, &internal_format, &format, &type, &has_alpha, &needs_swap)) { cairo_bool_t is_supported; clone = _cairo_image_surface_coerce (src); if (unlikely (status = clone->base.status)) goto FAIL; is_supported = _cairo_gl_get_image_format_and_type (ctx->gl_flavor, clone->pixman_format, &internal_format, &format, &type, &has_alpha, &needs_swap); assert (is_supported); assert (!needs_swap); src = clone; } cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8; status = _cairo_gl_surface_flush (&dst->base); if (unlikely (status)) goto FAIL; if (_cairo_gl_surface_is_texture (dst)) { void *data_start = src->data + src_y * src->stride + src_x * cpp; void *data_start_gles2 = NULL; /* * Due to GL_UNPACK_ROW_LENGTH missing in GLES2 we have to extract the * image data ourselves in some cases. In particular, we must extract * the pixels if: * a. we don't want full-length lines or * b. the row stride cannot be handled by GL itself using a 4 byte * alignment constraint */ if (src->stride < 0 || (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES && (src->width * cpp < src->stride - 3 || width != src->width))) { glPixelStorei (GL_UNPACK_ALIGNMENT, 1); status = _cairo_gl_surface_extract_image_data (src, src_x, src_y, width, height, &data_start_gles2); if (unlikely (status)) goto FAIL; data_start = data_start_gles2; } else { glPixelStorei (GL_UNPACK_ALIGNMENT, 4); if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp); } _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); glBindTexture (ctx->tex_target, dst->tex); glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexSubImage2D (ctx->tex_target, 0, dst_x, dst_y, width, height, format, type, data_start); free (data_start_gles2); /* If we just treated some rgb-only data as rgba, then we have to * go back and fix up the alpha channel where we filled in this * texture data. */ if (!has_alpha) { _cairo_gl_surface_fill_alpha_channel (dst, ctx, dst_x, dst_y, width, height); } } else { cairo_surface_t *tmp; tmp = _cairo_gl_surface_create_scratch (ctx, dst->base.content, width, height); if (unlikely (tmp->status)) goto FAIL; status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp, src, src_x, src_y, width, height, 0, 0); if (status == CAIRO_INT_STATUS_SUCCESS) { cairo_surface_pattern_t tmp_pattern; cairo_rectangle_int_t r; cairo_clip_t *clip; _cairo_pattern_init_for_surface (&tmp_pattern, tmp); cairo_matrix_init_translate (&tmp_pattern.base.matrix, -dst_x, -dst_y); tmp_pattern.base.filter = CAIRO_FILTER_NEAREST; tmp_pattern.base.extend = CAIRO_EXTEND_NONE; r.x = dst_x; r.y = dst_y; r.width = width; r.height = height; clip = _cairo_clip_intersect_rectangle (NULL, &r); status = _cairo_surface_paint (&dst->base, CAIRO_OPERATOR_SOURCE, &tmp_pattern.base, clip); _cairo_clip_destroy (clip); _cairo_pattern_fini (&tmp_pattern.base); } cairo_surface_destroy (tmp); } FAIL: status = _cairo_gl_context_release (ctx, status); if (clone) cairo_surface_destroy (&clone->base); return status; }
// but requires updating the texture if the piano changes which is slower (although still quite fast) // the other problem is the code is difficult to follow and maintain // can remove this when we know we aren't going to ever be using it void Piano::UpdateGLTexture() { extern GLenum g_texture_rectangle_format; int w = cc1->GetClientSize().x, h = GetHeight(), tex_w, tex_h; if(g_texture_rectangle_format == GL_TEXTURE_2D) tex_w = w, tex_h = h; else tex_w = NextPow2(w), tex_h = NextPow2(h); m_texcoords[0] = (float)w / tex_w; m_texcoords[1] = (float)h / tex_h; // this isn't very pretty but should at least be fast enough unsigned char bgcolor[4], tbgcolor[4]; SetColor(bgcolor, m_backBrush); SetColor(tbgcolor, m_backBrush); wxColour b = GetGlobalColor( _T("CHBLK") ); unsigned char bcolor[4] = {b.Red(), b.Green(), b.Blue(), 255}; ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle(); if(style->chartStatusWindowTransparent) tbgcolor[3] = 0; unsigned char *data = new unsigned char[4*w*h]; // fill to background color for(int x = 0; x < w; x++) { unsigned char *pos = data + 4*x; memcpy(pos, tbgcolor, 4); } for(int y = 1; y < 8; y++) { unsigned char *pos = data + 4*(y*w); memcpy(pos, data, 4*w); } int nKeys = m_key_array.GetCount(); // draw the keys for( int i = 0; i < nKeys; i++ ) { int key_db_index = m_key_array.Item( i ); if( -1 == key_db_index ) continue; bool selected = InArray(m_active_index_array, key_db_index); unsigned char color[4]; if( ChartData->GetDBChartType( key_db_index ) == CHART_TYPE_CM93 || ChartData->GetDBChartType( key_db_index ) == CHART_TYPE_CM93COMP ) { if(selected) SetColor(color, m_scBrush ); else SetColor(color, m_cBrush ); } else if( ChartData->GetDBChartFamily( key_db_index ) == CHART_FAMILY_VECTOR ) { if(selected) SetColor(color, m_svBrush ); else SetColor(color, m_vBrush ); } else { // Raster Chart if(selected) SetColor(color, m_slBrush ); else SetColor(color, m_tBrush ); } #if 0 // Check to see if this box appears in the sub_light array // If so, add a crosshatch pattern to the brush if(InArray(m_eclipsed_index_array, key_db_index)) { wxBrush ebrush( dc.GetBrush().GetColour(), wxCROSSDIAG_HATCH ); dc.SetBrush(ebrush); } #endif if(m_bBusy) SetColor(color, m_uvBrush ); wxRect box = KeyRect.Item( i ); bool eclipsed = InArray(m_eclipsed_index_array, key_db_index); int sympoint = m_brounded ? (eclipsed ? 5 : 3) : 1; for(int y = 0; y < 6; y++) { unsigned char *pos = data + 4*((box.y+y)*w + box.x); if(y > sympoint) { int line; if(y < box.height - sympoint) line = sympoint; else line = box.height-y-1; // shouldn't hit memcpy(pos, data + 4*((box.y+line)*w + box.x), 4*box.width); continue; } for(int x = 0; x < box.width; x++, pos+=4) { if(y == 0) { if( m_brounded && (x <= 2 || x >= box.width - 3) ) memcpy(pos, tbgcolor, 4); else memcpy(pos, bcolor, 4); } else if(m_brounded) { if(y == 1) { if(x == 0 || x == box.width - 1) memcpy(pos, tbgcolor, 4); else if(x == 1 || x == 2 || x == box.width - 3 || x == box.width - 2) memcpy(pos, bcolor, 4); else memcpy(pos, color, 4); } else if(y == 2) { if(x == 0 || x == box.width - 1) memcpy(pos, tbgcolor, 4); else if(x == 1 || x == box.width - 2) memcpy(pos, bcolor, 4); else memcpy(pos, color, 4); } else if(eclipsed) { if(x == 0 || x == box.width - 1) memcpy(pos, bcolor, 4); else { if(y == 3) { if(x <= 4 || x >= box.width - 5) memcpy(pos, color, 4); else memcpy(pos, bcolor, 4); } else if(y == 4) { if(x <= 3 || x >= box.width - 4) memcpy(pos, color, 4); else if(x == 4 || x == box.width - 5) memcpy(pos, bcolor, 4); else memcpy(pos, bgcolor, 4); } else { if(x <= 2 || x >= box.width - 3) memcpy(pos, color, 4); else if(x == 3 || x == box.width - 4) memcpy(pos, bcolor, 4); else memcpy(pos, bgcolor, 4); } } } else goto def; } else { def: if(x == 0 || x == box.width - 1) memcpy(pos, bcolor, 4); else memcpy(pos, color, 4); } } } } // quickly fill the rest via symmetry for(int y = 8; y < h; y++) { int line; if(y < h - 7) line = 7; else line = h-y-1; memcpy(data + 4*(y*w), data + 4*(line*w), 4*w); } if(!m_tex) glGenTextures( 1, &m_tex ); glBindTexture(GL_TEXTURE_2D, m_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if(g_texture_rectangle_format == GL_TEXTURE_2D) glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); else { glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 ); glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data ); } delete [] data; }
// build a texture to hold minimum sized rectangles and icons used to render the chart bar // this texture is only updated if the color scheme or chart bar height change void Piano::BuildGLTexture() { int h = GetHeight(); wxBrush tbackBrush; // transparent back brush ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle(); if(style->chartStatusWindowTransparent) tbackBrush = wxColour(1,1,1); else tbackBrush = m_backBrush; wxBrush brushes[] = { m_scBrush, m_cBrush, m_svBrush, m_vBrush, m_slBrush, m_tBrush, m_uvBrush }; m_tex_piano_height = h; m_texw = 64; m_texh = ((sizeof brushes) / (sizeof *brushes)) * h; m_texh += 4*16; // for icons; m_texh = NextPow2(m_texh); if(!m_tex) glGenTextures( 1, &m_tex ); glBindTexture(GL_TEXTURE_2D, m_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); wxBitmap bmp(m_texw, m_texh); wxMemoryDC dc(bmp); dc.SetPen( *wxTRANSPARENT_PEN ); dc.SetBrush(tbackBrush); dc.DrawRectangle(0, 0, m_texw, m_texh); // draw the needed rectangles with minimal width wxPen ppPen( GetGlobalColor( _T("CHBLK") ), 1, wxPENSTYLE_SOLID ); dc.SetPen( ppPen ); for(unsigned int b = 0; b < (sizeof brushes) / (sizeof *brushes); b++) { unsigned int x = 0, y = h * b; dc.SetBrush(brushes[b]); int u = 3, v = 2; dc.DrawRectangle(x+u, y+v, 3, h-2*v); x+=3+2*u; dc.DrawRoundedRectangle(x+u, y+v, 9, h-2*v, 4); x+=9+2*u; int w = 3; dc.DrawRoundedRectangle(x+u, y+v, 12, h-2*v, 4); dc.SetBrush( m_backBrush ); dc.DrawRoundedRectangle(x+u+w, y+v+w, 12-2*w, h-2*v-2*w, 3); x+=12+2*u; if(x >= m_texw) printf("texture too small\n"); } dc.SelectObject( wxNullBitmap ); wxImage image = bmp.ConvertToImage(); unsigned char *data = new unsigned char[4*m_texw*m_texh], *d = data, *e = image.GetData(), *a = image.GetAlpha(); for(unsigned int i=0; i<m_texw*m_texh; i++) { if(style->chartStatusWindowTransparent && e[0] == 1 && e[1] == 1 && e[2] == 1) d[3] = 0; else d[3] = 255; memcpy(d, e, 3), d+=4, e+=3; } glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_texw, m_texh, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); delete [] data; // put the bitmaps in below wxBitmap *bitmaps[] = {m_pInVizIconBmp, m_pTmercIconBmp, m_pSkewIconBmp, m_pPolyIconBmp}; for(unsigned int i = 0; i < (sizeof bitmaps) / (sizeof *bitmaps); i++) { int iw = bitmaps[i]->GetWidth(), ih = bitmaps[i]->GetHeight(); wxASSERT(ih <= 16); wxImage im = bitmaps[i]->ConvertToImage(); unsigned char *data = new unsigned char[4*iw*ih], *d = data, *e = im.GetData(), *a = im.GetAlpha(); for(int j = 0; j<iw*ih; j++) { memcpy(d, e, 3), d+=3, e+=3; *d = *a, d++, a++; } int off = ((sizeof brushes) / (sizeof *brushes))*h + 16*i; glTexSubImage2D( GL_TEXTURE_2D, 0, 0, off, iw, ih, GL_RGBA, GL_UNSIGNED_BYTE, data ); delete [] data; } }
/** * Create a texture image with reference values. Draw a textured quad. * Save reference image with glReadPixels(). * Loop: * replace a sub-region of the texture image with same values * draw test textured quad * read test image with glReadPixels * compare reference image to test image * \param target GL_TEXTURE_1D/2D/3D * \param intFormat the internal texture format */ static GLboolean test_format(GLenum target, GLenum intFormat) { const GLenum srcFormat = GL_RGBA; GLuint w = 128, h = 64, d = 8; GLuint tex, i, j, k, n, t; GLubyte *img, *ref, *testImg; GLboolean pass = GL_TRUE; GLuint bw, bh, wMask, hMask, dMask; get_format_block_size(intFormat, &bw, &bh); wMask = ~(bw-1); hMask = ~(bh-1); dMask = ~0; if (target != GL_TEXTURE_3D) d = 1; if (target == GL_TEXTURE_1D) h = 1; img = (GLubyte *) malloc(w * h * d * 4); ref = (GLubyte *) malloc(w * h * d * 4); testImg = (GLubyte *) malloc(w * h * d * 4); /* fill source tex image */ n = 0; for (i = 0; i < d; i++) { for (j = 0; j < h; j++) { for (k = 0; k < w; k++) { img[n++] = j * 4; img[n++] = k * 2; img[n++] = i * 16; img[n++] = 255; } } } glPixelStorei(GL_UNPACK_ROW_LENGTH, w); glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, h); glGenTextures(1, &tex); glBindTexture(target, tex); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0); if (target == GL_TEXTURE_1D) { glTexImage1D(target, 0, intFormat, w, 0, srcFormat, GL_UNSIGNED_BYTE, img); } else if (target == GL_TEXTURE_2D) { glTexImage2D(target, 0, intFormat, w, h, 0, srcFormat, GL_UNSIGNED_BYTE, img); } else if (target == GL_TEXTURE_3D) { glTexImage3D(target, 0, intFormat, w, h, d, 0, srcFormat, GL_UNSIGNED_BYTE, img); } glEnable(target); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); /* draw reference image */ glClear(GL_COLOR_BUFFER_BIT); piglit_draw_rect_tex3d(0, 0, w, h, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0); glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ref); for (t = 0; t < 10; t++) { /* Choose random region of texture to update. * Use sizes and positions that are multiples of * the compressed block size. */ GLint tw = (rand() % w) & wMask; GLint th = (rand() % h) & hMask; GLint td = (rand() % d) & dMask; GLint tx = (rand() % (w - tw)) & wMask; GLint ty = (rand() % (h - th)) & hMask; GLint tz = (rand() % (d - td)) & dMask; assert(tx + tw <= w); assert(ty + th <= h); assert(tz + td <= d); /* replace texture region (with same data) */ glPixelStorei(GL_UNPACK_SKIP_PIXELS, tx); glPixelStorei(GL_UNPACK_SKIP_ROWS, ty); glPixelStorei(GL_UNPACK_SKIP_IMAGES, tz); if (target == GL_TEXTURE_1D) { glTexSubImage1D(target, 0, tx, tw, srcFormat, GL_UNSIGNED_BYTE, img); } else if (target == GL_TEXTURE_2D) { glTexSubImage2D(target, 0, tx, ty, tw, th, srcFormat, GL_UNSIGNED_BYTE, img); } else if (target == GL_TEXTURE_2D) { glTexSubImage3D(target, 0, tx, ty, tz, tw, th, td, srcFormat, GL_UNSIGNED_BYTE, img); } /* draw test image */ glClear(GL_COLOR_BUFFER_BIT); piglit_draw_rect_tex3d(0, 0, w, h, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0); glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, testImg); piglit_present_results(); if (!equal_images(ref, testImg, w, h)) { printf("texsubimage failed\n"); printf(" target: %s\n", piglit_get_gl_enum_name(target)); printf(" internal format: %s\n", piglit_get_gl_enum_name(intFormat)); printf(" region: %d, %d %d x %d\n", tx, ty, tw, th); pass = GL_FALSE; break; } } glDisable(target); free(img); free(ref); free(testImg); glDeleteTextures(1, &tex); return pass; }
void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) { if (ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::fillTexture(c, glyph); glBindTexture(GL_TEXTURE_2D, m_texture); const QImage &texture = image(); const uchar *bits = texture.constBits(); bits += c.y * texture.bytesPerLine() + c.x; for (int i=0; i<c.h; ++i) { glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits); bits += texture.bytesPerLine(); } return; } QImage mask = textureMapForGlyph(glyph); const int maskWidth = mask.width(); const int maskHeight = mask.height(); if (mask.format() == QImage::Format_Mono) { mask = mask.convertToFormat(QImage::Format_Indexed8); for (int y = 0; y < maskHeight; ++y) { uchar *src = (uchar *) mask.scanLine(y); for (int x = 0; x < maskWidth; ++x) src[x] = -src[x]; // convert 0 and 1 into 0 and 255 } } else if (mask.format() == QImage::Format_RGB32) { // Make the alpha component equal to the average of the RGB values. // This is needed when drawing sub-pixel antialiased text on translucent targets. for (int y = 0; y < maskHeight; ++y) { quint32 *src = (quint32 *) mask.scanLine(y); for (int x = 0; x < maskWidth; ++x) { uchar r = src[x] >> 16; uchar g = src[x] >> 8; uchar b = src[x]; quint32 avg = (quint32(r) + quint32(g) + quint32(b) + 1) / 3; // "+1" for rounding. src[x] = (src[x] & 0x00ffffff) | (avg << 24); } } } glBindTexture(GL_TEXTURE_2D, m_texture); if (mask.format() == QImage::Format_RGB32) { glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits()); } else { #ifdef QT_OPENGL_ES2 glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits()); #else // glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is // not a multiple of four bytes. The bug appeared on a computer with 32-bit Windows Vista // and nVidia GeForce 8500GT. GL_UNPACK_ALIGNMENT is set to four bytes, 'mask' has a // multiple of four bytes per line, and most of the glyph shows up correctly in the // texture, which makes me think that this is a driver bug. // One workaround is to make sure the mask width is a multiple of four bytes, for instance // by converting it to a format with four bytes per pixel. Another is to copy one line at a // time. for (int i = 0; i < maskHeight; ++i) glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i)); #endif } }
void QGLTextureGlyphCache::resizeTextureData(int width, int height) { int oldWidth = m_width; int oldHeight = m_height; // Make the lower glyph texture size 16 x 16. if (width < 16) width = 16; if (height < 16) height = 16; GLuint oldTexture = m_texture; createTextureData(width, height); if (ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::resizeTextureData(width, height); Q_ASSERT(image().depth() == 8); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); glDeleteTextures(1, &oldTexture); return; } // ### the QTextureGlyphCache API needs to be reworked to allow // ### resizeTextureData to fail glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); GLuint tmp_texture; glGenTextures(1, &tmp_texture); glBindTexture(GL_TEXTURE_2D, tmp_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tmp_texture, 0); glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); glBindTexture(GL_TEXTURE_2D, oldTexture); pex->transferMode(BrushDrawingMode); glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glViewport(0, 0, oldWidth, oldHeight); GLfloat* vertexCoordinateArray = pex->staticVertexCoordinateArray; vertexCoordinateArray[0] = -1.0f; vertexCoordinateArray[1] = -1.0f; vertexCoordinateArray[2] = 1.0f; vertexCoordinateArray[3] = -1.0f; vertexCoordinateArray[4] = 1.0f; vertexCoordinateArray[5] = 1.0f; vertexCoordinateArray[6] = -1.0f; vertexCoordinateArray[7] = 1.0f; GLfloat* textureCoordinateArray = pex->staticTextureCoordinateArray; textureCoordinateArray[0] = 0.0f; textureCoordinateArray[1] = 0.0f; textureCoordinateArray[2] = 1.0f; textureCoordinateArray[3] = 0.0f; textureCoordinateArray[4] = 1.0f; textureCoordinateArray[5] = 1.0f; textureCoordinateArray[6] = 0.0f; textureCoordinateArray[7] = 1.0f; pex->setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, vertexCoordinateArray); pex->setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, textureCoordinateArray); pex->shaderManager->useBlitProgram(); pex->shaderManager->blitProgram()->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glBindTexture(GL_TEXTURE_2D, m_texture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, 0); glDeleteTextures(1, &tmp_texture); glDeleteTextures(1, &oldTexture); glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); glViewport(0, 0, pex->width, pex->height); pex->updateClipScissorTest(); }
void CScreensaverPlasma::Render() { glDisable(GL_BLEND); int i, j; float rgb[3]; float temp; int index; //Update constants for (i = 0; i < NUMCONSTS; i++) { m_ct[i] += m_cv[i]; if(m_ct[i] > PIx2) m_ct[i] -= PIx2; m_c[i] = sinf(m_ct[i]) * m_focus; } // Update colors for(i = 0; i < m_plasmasize; i++) { for(j = 0; j < int(float(m_plasmasize) / m_aspectRatio); j++) { // Calculate vertex colors rgb[0] = m_plasma[i][j][0]; rgb[1] = m_plasma[i][j][1]; rgb[2] = m_plasma[i][j][2]; m_plasma[i][j][0] = 0.7f * (m_c[0] * m_position[i][j][0] + m_c[1] * m_position[i][j][1] + m_c[2] * (m_position[i][j][0] * m_position[i][j][0] + 1.0f) + m_c[3] * m_position[i][j][0] * m_position[i][j][1] + m_c[4] * rgb[1] + m_c[5] * rgb[2]); m_plasma[i][j][1] = 0.7f * (m_c[6] * m_position[i][j][0] + m_c[7] * m_position[i][j][1] + m_c[8] * m_position[i][j][0] * m_position[i][j][0] + m_c[9] * (m_position[i][j][1] * m_position[i][j][1] - 1.0f) + m_c[10] * rgb[0] + m_c[11] * rgb[2]); m_plasma[i][j][2] = 0.7f * (m_c[12] * m_position[i][j][0] + m_c[13] * m_position[i][j][1] + m_c[14] * (1.0f - m_position[i][j][0] * m_position[i][j][1]) + m_c[15] * m_position[i][j][1] * m_position[i][j][1] + m_c[16] * rgb[0] + m_c[17] * rgb[1]); // Don't let the colors change too much temp = m_plasma[i][j][0] - rgb[0]; if(temp > m_maxdiff) m_plasma[i][j][0] = rgb[0] + m_maxdiff; if(temp < -m_maxdiff) m_plasma[i][j][0] = rgb[0] - m_maxdiff; temp = m_plasma[i][j][1] - rgb[1]; if(temp > m_maxdiff) m_plasma[i][j][1] = rgb[1] + m_maxdiff; if(temp < -m_maxdiff) m_plasma[i][j][1] = rgb[1] - m_maxdiff; temp = m_plasma[i][j][2] - rgb[2]; if(temp > m_maxdiff) m_plasma[i][j][2] = rgb[2] + m_maxdiff; if(temp < -m_maxdiff) m_plasma[i][j][2] = rgb[2] - m_maxdiff; // Put colors into texture index = (i * TEXSIZE + j) * 3; m_plasmamap[index] = fabstrunc(m_plasma[i][j][0]); m_plasmamap[index+1] = fabstrunc(m_plasma[i][j][1]); m_plasmamap[index+2] = fabstrunc(m_plasma[i][j][2]); } } // Update texture if (!glIsTexture(m_tex)) { glGenTextures(1, &m_tex); glBindTexture(GL_TEXTURE_2D, m_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, TEXSIZE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_RGB, GL_FLOAT, m_plasmamap); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } else { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, TEXSIZE); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, int(float(m_plasmasize) / m_aspectRatio), m_plasmasize, GL_RGB, GL_FLOAT, m_plasmamap); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } // Draw it // The "- 1" cuts off right and top edges to get rid of blending to black float texright = float(m_plasmasize - 1) / float(TEXSIZE); float textop = float(int(float(m_plasmasize) / m_aspectRatio) - 1) / float(TEXSIZE); struct PackedVertex { float x, y, z; float u1, v1; } packets[4]; packets[0].x = -1.0f; packets[0].y = -1.0f; packets[0].z = 0.0f; packets[0].u1 = 0.0f; packets[0].v1 = 0.0f; packets[1].x = 1.0f; packets[1].y = -1.0f; packets[1].z = 0.0f; packets[1].u1 = 0.0f; packets[1].v1 = texright; packets[2].x = -1.0f; packets[2].y = 1.0f; packets[2].z = 0.0f; packets[2].u1 = textop; packets[2].v1 = 0.0f; packets[3].x = 1.0f; packets[3].y = 1.0f; packets[3].z = 0.0f; packets[3].u1 = textop; packets[3].v1 = texright; EnableShader(); glBindBuffer(GL_ARRAY_BUFFER, m_vertexVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(PackedVertex)*4, &packets[0], GL_STATIC_DRAW); glVertexAttribPointer(m_hPos, 3, GL_FLOAT, 0, sizeof(PackedVertex), BUFFER_OFFSET(offsetof(PackedVertex, x))); glEnableVertexAttribArray(m_hPos); glVertexAttribPointer(m_hCord, 2, GL_FLOAT, 0, sizeof(PackedVertex), BUFFER_OFFSET(offsetof(PackedVertex, u1))); glEnableVertexAttribArray(m_hCord); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableVertexAttribArray(m_hPos); glDisableVertexAttribArray(m_hCord); glBindBuffer(GL_ARRAY_BUFFER, 0); DisableShader(); glBindTexture(GL_TEXTURE_2D, 0); }
void EuphoriaWidget::paintGL() { int i; static double lastTime = timeGetTime(); // update time elapsedTime = timeGetTime() - lastTime; lastTime += elapsedTime; _ec = this; // Update wisps for(i=0; i<dWisps; i++) _wisps[i].update(); for(i=0; i<dBackground; i++) _backwisps[i].update(); if(dFeedback) { float feedbackIntensity = float(dFeedback) / 101.0f; // update feedback variables for(i=0; i<4; i++) { fr[i] += elapsedTime * fv[i]; if(fr[i] > PIx2) fr[i] -= PIx2; } f[0] = 30.0f * cos(fr[0]); f[1] = 0.2f * cos(fr[1]); f[2] = 0.2f * cos(fr[2]); f[3] = 0.8f * cos(fr[3]); for(i=0; i<3; i++) { lr[i] += elapsedTime * lv[i]; if(lr[i] > PIx2) lr[i] -= PIx2; l[i] = cos(lr[i]); l[i] = l[i] * l[i]; } // Create drawing area for feedback texture glViewport(0, 0, feedbacktexsize, feedbacktexsize); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(30.0, aspectRatio, 0.01f, 20.0f); glMatrixMode(GL_MODELVIEW); // Draw glClear(GL_COLOR_BUFFER_BIT); glColor3f(feedbackIntensity, feedbackIntensity, feedbackIntensity); glBindTexture(GL_TEXTURE_2D, feedbacktex); glPushMatrix(); glTranslatef(f[1] * l[1], f[2] * l[1], f[3] * l[2]); glRotatef(f[0] * l[0], 0, 0, 1); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(-0.5f, -0.5f); glVertex3f(-aspectRatio*2.0f, -2.0f, 1.25f); glTexCoord2f(1.5f, -0.5f); glVertex3f(aspectRatio*2.0f, -2.0f, 1.25f); glTexCoord2f(-0.5f, 1.5f); glVertex3f(-aspectRatio*2.0f, 2.0f, 1.25f); glTexCoord2f(1.5f, 1.5f); glVertex3f(aspectRatio*2.0f, 2.0f, 1.25f); glEnd(); glPopMatrix(); glBindTexture(GL_TEXTURE_2D, texName); for(i=0; i<dBackground; i++) _backwisps[i].drawAsBackground(); for(i=0; i<dWisps; i++) _wisps[i].draw(); // readback feedback texture glReadBuffer(GL_BACK); glPixelStorei(GL_UNPACK_ROW_LENGTH, feedbacktexsize); glBindTexture(GL_TEXTURE_2D, feedbacktex); glReadPixels(0, 0, feedbacktexsize, feedbacktexsize, GL_RGB, GL_UNSIGNED_BYTE, feedbackmap); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, feedbacktexsize, feedbacktexsize, GL_RGB, GL_UNSIGNED_BYTE, feedbackmap); // create regular drawing area glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(20.0, aspectRatio, 0.01f, 20.0f); glMatrixMode(GL_MODELVIEW); // Draw again glClear(GL_COLOR_BUFFER_BIT); glColor3f(feedbackIntensity, feedbackIntensity, feedbackIntensity); glPushMatrix(); glTranslatef(f[1] * l[1], f[2] * l[1], f[3] * l[2]); glRotatef(f[0] * l[0], 0, 0, 1); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(-0.5f, -0.5f); glVertex3f(-aspectRatio*2.0f, -2.0f, 1.25f); glTexCoord2f(1.5f, -0.5f); glVertex3f(aspectRatio*2.0f, -2.0f, 1.25f); glTexCoord2f(-0.5f, 1.5f); glVertex3f(-aspectRatio*2.0f, 2.0f, 1.25f); glTexCoord2f(1.5f, 1.5f); glVertex3f(aspectRatio*2.0f, 2.0f, 1.25f); glEnd(); glPopMatrix(); glBindTexture(GL_TEXTURE_2D, texName); } else glClear(GL_COLOR_BUFFER_BIT); // for(i=0; i<dBackground; i++) _backwisps[i].drawAsBackground(); for(i=0; i<dWisps; i++) _wisps[i].draw(); glFlush(); }
static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, int depth, char err_out[256]) { GPUTexture *tex; GLenum type, format, internalformat; void *pixels = NULL; if (depth && !GLEW_ARB_depth_texture) return NULL; tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); tex->w = w; tex->h = h; tex->number = -1; tex->refcount = 1; tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D; tex->depth = depth; glGenTextures(1, &tex->bindcode); if (!tex->bindcode) { if (err_out) { BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d", (int)glGetError()); } else { fprintf(stderr, "GPUTexture: texture create failed: %d\n", (int)glGetError()); } GPU_texture_free(tex); return NULL; } if (!GPU_non_power_of_two_support()) { tex->w = power_of_2_max_i(tex->w); tex->h = power_of_2_max_i(tex->h); } tex->number = 0; glBindTexture(tex->target, tex->bindcode); if (depth) { type = GL_UNSIGNED_BYTE; format = GL_DEPTH_COMPONENT; internalformat = GL_DEPTH_COMPONENT; } else { type = GL_UNSIGNED_BYTE; format = GL_RGBA; internalformat = GL_RGBA8; if (fpixels) pixels = GPU_texture_convert_pixels(w*h, fpixels); } if (tex->target == GL_TEXTURE_1D) { glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL); if (fpixels) { glTexSubImage1D(tex->target, 0, 0, w, format, type, pixels ? pixels : fpixels); if (tex->w > w) GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, 1); } } else { glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, type, NULL); if (fpixels) { glTexSubImage2D(tex->target, 0, 0, 0, w, h, format, type, pixels ? pixels : fpixels); if (tex->w > w) GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h); if (tex->h > h) GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h); } } if (pixels) MEM_freeN(pixels); if (depth) { glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); } else { glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } if (tex->target != GL_TEXTURE_1D) { /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */ GLenum wrapmode = (depth || tex->h == 1)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER; glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode); glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode); #if 0 float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); #endif } else glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); return tex; }
void Texture2D::Init(ImagePullStream &stream) { mTex = 0; uint8_t *scanline = 0; uint8_t *extendedScanline = 0; try { mWidth = stream.GetWidth(); mHeight = stream.GetHeight(); glGenTextures(1,&mTex); CheckGLErrors(); glBindTexture(GL_TEXTURE_2D,mTex); CheckGLErrors(); int format; switch(stream.GetNumChannels()) { case 1: format = GL_LUMINANCE; break; case 3: format = GL_RGBA; break; case 4: format = GL_RGBA; break; default: throw Exception("Unsupported number of channels."); } glTexImage2D(GL_TEXTURE_2D,0,format,mWidth,mHeight,0,format,GL_UNSIGNED_BYTE,0); CheckGLErrors(); scanline = new uint8_t[mWidth * stream.GetNumChannels()]; if(stream.GetNumChannels() == 3) { extendedScanline = new uint8_t[mWidth * 4]; for(int y = 0;y < mHeight;y++) { stream.StreamScanline(scanline); uint8_t *readPtr = scanline; uint8_t *writePtr = extendedScanline; for(int x = 0;x < mWidth;x++) { for(int i = 0;i < 3;i++) *(writePtr++) = *(readPtr++); *(writePtr++) = 0xff; } glTexSubImage2D(GL_TEXTURE_2D,0,0,y,mWidth,1,format,GL_UNSIGNED_BYTE,extendedScanline); CheckGLErrors(); } } else { for(int y = 0;y < mHeight;y++) { stream.StreamScanline(scanline); glTexSubImage2D(GL_TEXTURE_2D,0,0,y,mWidth,1,format,GL_UNSIGNED_BYTE,scanline); CheckGLErrors(); } } glGenerateMipmap(GL_TEXTURE_2D); CheckGLErrors(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); CheckGLErrors(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CheckGLErrors(); delete [] scanline; delete [] extendedScanline; } catch(...) { if(mTex) glDeleteTextures(1, &mTex); delete [] scanline; delete [] extendedScanline; throw; } }
unsigned int PointMan::GetIconTexture( const wxBitmap *pbm, int &glw, int &glh ) { #ifdef ocpnUSE_GL int index = GetIconIndex( pbm ); ODMarkIcon *pmi = (ODMarkIcon *) m_pIconArray->Item( index ); assert(pmi != 0); unsigned int *IconTexture; switch (m_ColourScheme) { case PI_GLOBAL_COLOR_SCHEME_RGB: IconTexture = &pmi->icon_texture_RGB; break; case PI_GLOBAL_COLOR_SCHEME_DAY: IconTexture = &pmi->icon_texture_Day; break; case PI_GLOBAL_COLOR_SCHEME_DUSK: IconTexture = &pmi->icon_texture_Dusk; break; case PI_GLOBAL_COLOR_SCHEME_NIGHT: IconTexture = &pmi->icon_texture_Night; break; default: IconTexture = &pmi->icon_texture_Day; break; } if(*IconTexture == 0) { /* make rgba texture */ glGenTextures(1, IconTexture); glBindTexture(GL_TEXTURE_2D, *IconTexture); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); wxImage image = pbm->ConvertToImage(); int w = image.GetWidth(), h = image.GetHeight(); pmi->tex_w = NextPow2(w); pmi->tex_h = NextPow2(h); unsigned char *d = image.GetData(); unsigned char *a = image.GetAlpha(); unsigned char mr, mg, mb; if(!a) image.GetOrFindMaskColour( &mr, &mg, &mb ); unsigned char *e = new unsigned char[4 * w * h]; if(d && e){ 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 ); } } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pmi->tex_w, pmi->tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, e); delete [] e; } glw = pmi->tex_w; glh = pmi->tex_h; return *IconTexture; #else return 0; #endif }
void GlobalModel::clean(const Eigen::Matrix4f & pose, const int & time, GPUTexture * indexMap, GPUTexture * vertConfMap, GPUTexture * colorTimeMap, GPUTexture * normRadMap, GPUTexture * depthMap, const float confThreshold, std::vector<float> & graph, const int timeDelta, const float maxDepth, const bool isFern) { assert(graph.size() / 16 < MAX_NODES); if(graph.size() > 0) { //Can be optimised by only uploading new nodes with offset glBindTexture(GL_TEXTURE_2D, deformationNodes.texture->tid); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, graph.size(), 1, GL_LUMINANCE, GL_FLOAT, graph.data()); } TICK("Fuse::Copy"); //Next we copy the new unstable vertices from the newUnstableFid transform feedback into the global map unstableProgram->Bind(); unstableProgram->setUniform(Uniform("time", time)); unstableProgram->setUniform(Uniform("confThreshold", confThreshold)); unstableProgram->setUniform(Uniform("scale", (float)IndexMap::FACTOR)); unstableProgram->setUniform(Uniform("indexSampler", 0)); unstableProgram->setUniform(Uniform("vertConfSampler", 1)); unstableProgram->setUniform(Uniform("colorTimeSampler", 2)); unstableProgram->setUniform(Uniform("normRadSampler", 3)); unstableProgram->setUniform(Uniform("nodeSampler", 4)); unstableProgram->setUniform(Uniform("depthSampler", 5)); unstableProgram->setUniform(Uniform("nodes", (float)(graph.size() / 16))); unstableProgram->setUniform(Uniform("nodeCols", (float)NODE_TEXTURE_DIMENSION)); unstableProgram->setUniform(Uniform("timeDelta", timeDelta)); unstableProgram->setUniform(Uniform("maxDepth", maxDepth)); unstableProgram->setUniform(Uniform("isFern", (int)isFern)); Eigen::Matrix4f t_inv = pose.inverse(); unstableProgram->setUniform(Uniform("t_inv", t_inv)); unstableProgram->setUniform(Uniform("cam", Eigen::Vector4f(Intrinsics::getInstance().cx(), Intrinsics::getInstance().cy(), Intrinsics::getInstance().fx(), Intrinsics::getInstance().fy()))); unstableProgram->setUniform(Uniform("cols", (float)Resolution::getInstance().cols())); unstableProgram->setUniform(Uniform("rows", (float)Resolution::getInstance().rows())); glBindBuffer(GL_ARRAY_BUFFER, vbos[target].first); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, Vertex::SIZE, 0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, Vertex::SIZE, reinterpret_cast<GLvoid*>(sizeof(Eigen::Vector4f))); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, Vertex::SIZE, reinterpret_cast<GLvoid*>(sizeof(Eigen::Vector4f) * 2)); glEnable(GL_RASTERIZER_DISCARD); glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, vbos[renderSource].second); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbos[renderSource].first); glBeginTransformFeedback(GL_POINTS); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, indexMap->texture->tid); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, vertConfMap->texture->tid); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, colorTimeMap->texture->tid); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, normRadMap->texture->tid); glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_2D, deformationNodes.texture->tid); glActiveTexture(GL_TEXTURE5); glBindTexture(GL_TEXTURE_2D, depthMap->texture->tid); glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, countQuery); glDrawTransformFeedback(GL_POINTS, vbos[target].second); glBindBuffer(GL_ARRAY_BUFFER, newUnstableVbo); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, Vertex::SIZE, 0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, Vertex::SIZE, reinterpret_cast<GLvoid*>(sizeof(Eigen::Vector4f))); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, Vertex::SIZE, reinterpret_cast<GLvoid*>(sizeof(Eigen::Vector4f) * 2)); glDrawTransformFeedback(GL_POINTS, newUnstableFid); glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); glGetQueryObjectuiv(countQuery, GL_QUERY_RESULT, &count); glEndTransformFeedback(); glDisable(GL_RASTERIZER_DISCARD); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); unstableProgram->Unbind(); std::swap(target, renderSource); glFinish(); TOCK("Fuse::Copy"); }
stash::sth_glyph* stash::sth_font::get_glyph(unsigned int codepoint, short isize) { // Find code point and size. std::pair<unsigned int,int> key(codepoint, isize); if (glyphs.find( key ) != glyphs.end() ) return &glyphs.find( key )->second; // Could not find glyph, create it. int advance,lsb,x0,y0,x1,y1; int g = stbtt_FindGlyphIndex(&font, codepoint); float scale = stbtt_ScaleForPixelHeight(&font, isize/10.0f); stbtt_GetGlyphHMetrics(&font, g, &advance, &lsb); stbtt_GetGlyphBitmapBox(&font, g, scale,scale, &x0,&y0,&x1,&y1); int gw = x1-x0; int gh = y1-y0; // Find row where the glyph can be fit (vertically first, then horizontally) sth_row* br = 0; int rh = (gh+7) & ~7; for (size_t i = 0; i < rows->size() && !br; ++i) { if (rows->at(i).h == rh && rows->at(i).x+gw+1 <= tw) br = &rows->at(i); } // If no row found, add new. if (br == NULL) { short py = 0; // Check that there is enough space. if (rows->size()) { py = rows->back().y + rows->back().h+1; if (py+rh > th) return 0; } // Init and add row rows->push_back( sth_row(0,py,rh) ); br = &rows->back(); } // Init glyph. sth_glyph glyph; glyph.codepoint = codepoint; glyph.size = isize; glyph.x0 = br->x; glyph.y0 = br->y; glyph.x1 = glyph.x0+gw; glyph.y1 = glyph.y0+gh; glyph.xadv = scale * advance; glyph.xoff = (float)x0; glyph.yoff = (float)y0; // glyphs[ key ] = glyphs[ key ]; glyphs[ key ] = glyph; // Advance row location. br->x += gw+1; // Rasterize std::vector< unsigned char > bmp(gw*gh); if( bmp.size() ) { stbtt_MakeGlyphBitmap(&font, &bmp[0], gw,gh,gw, scale,scale, g); // Update texture glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glTexSubImage2D(GL_TEXTURE_2D, 0, glyph.x0,glyph.y0, gw,gh, GL_ALPHA,GL_UNSIGNED_BYTE,&bmp[0]); } return &glyphs[ key ]; }
/* ======================== idImage::SubImageUpload ======================== */ void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int height, const void* pic, int pixelPitch ) const { assert( x >= 0 && y >= 0 && mipLevel >= 0 && width >= 0 && height >= 0 && mipLevel < opts.numLevels ); int compressedSize = 0; if( IsCompressed() ) { assert( !( x & 3 ) && !( y & 3 ) ); // compressed size may be larger than the dimensions due to padding to quads int quadW = ( width + 3 ) & ~3; int quadH = ( height + 3 ) & ~3; compressedSize = quadW * quadH * BitsForFormat( opts.format ) / 8; int padW = ( opts.width + 3 ) & ~3; int padH = ( opts.height + 3 ) & ~3; assert( x + width <= padW && y + height <= padH ); // upload the non-aligned value, OpenGL understands that there // will be padding if( x + width > opts.width ) { width = opts.width - x; } if( y + height > opts.height ) { height = opts.height - x; } } else { assert( x + width <= opts.width && y + height <= opts.height ); } int target; int uploadTarget; if( opts.textureType == TT_2D ) { target = GL_TEXTURE_2D; uploadTarget = GL_TEXTURE_2D; } else if( opts.textureType == TT_CUBIC ) { target = GL_TEXTURE_CUBE_MAP; uploadTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + z; } else { assert( !"invalid opts.textureType" ); target = GL_TEXTURE_2D; uploadTarget = GL_TEXTURE_2D; } glBindTexture( target, texnum ); if( pixelPitch != 0 ) { glPixelStorei( GL_UNPACK_ROW_LENGTH, pixelPitch ); } if( opts.format == FMT_RGB565 ) { glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_TRUE ); } #ifdef DEBUG GL_CheckErrors(); #endif if( IsCompressed() ) { glCompressedTexSubImage2D( uploadTarget, mipLevel, x, y, width, height, internalFormat, compressedSize, pic ); } else { // make sure the pixel store alignment is correct so that lower mips get created // properly for odd shaped textures - this fixes the mip mapping issues with // fonts int unpackAlignment = width * BitsForFormat( ( textureFormat_t )opts.format ) / 8; if( ( unpackAlignment & 3 ) == 0 ) { glPixelStorei( GL_UNPACK_ALIGNMENT, 4 ); } else { glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); } glTexSubImage2D( uploadTarget, mipLevel, x, y, width, height, dataFormat, dataType, pic ); } #ifdef DEBUG GL_CheckErrors(); #endif if( opts.format == FMT_RGB565 ) { glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE ); } if( pixelPitch != 0 ) { glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); } }
SpriteFont::SpriteFont(const char* font, int size, char cs, char ce) { // Initialize SDL_ttf if (!TTF_WasInit()) { TTF_Init(); } TTF_Font* f = TTF_OpenFont(font, size); if (f == nullptr) { fprintf(stderr, "Failed to open TTF font %s\n", font); fflush(stderr); throw 281; } _fontHeight = TTF_FontHeight(f); _regStart = cs; _regLength = ce - cs + 1; int padding = size / 8; // First neasure all the regions glm::ivec4* glyphRects = new glm::ivec4[_regLength]; int i = 0, advance; for (char c = cs; c <= ce; c++) { TTF_GlyphMetrics(f, c, &glyphRects[i].x, &glyphRects[i].z, &glyphRects[i].y, &glyphRects[i].w, &advance); glyphRects[i].z -= glyphRects[i].x; glyphRects[i].x = 0; glyphRects[i].w -= glyphRects[i].y; glyphRects[i].y = 0; i++; } // Find best partitioning of glyphs int rows = 1, w, h, bestWidth = 0, bestHeight = 0, area = MAX_TEXTURE_RES * MAX_TEXTURE_RES, bestRows = 0; std::vector<int>* bestPartition = nullptr; while (rows <= _regLength) { h = rows * (padding + _fontHeight) + padding; auto gr = createRows(glyphRects, _regLength, rows, padding, w); // Desire a power of 2 texture w = closestPow2(w); h = closestPow2(h); // A texture must be feasible if (w > MAX_TEXTURE_RES || h > MAX_TEXTURE_RES) { rows++; delete[] gr; continue; } // Check for minimal area if (area >= w * h) { if (bestPartition) delete[] bestPartition; bestPartition = gr; bestWidth = w; bestHeight = h; bestRows = rows; area = bestWidth * bestHeight; rows++; } else { delete[] gr; break; } } // Can a bitmap font be made? if (!bestPartition) { fprintf(stderr, "Failed to Map TTF font %s to texture. Try lowering resolution.\n", font); fflush(stderr); throw 282; } // Create the texture glGenTextures(1, &_texID); glBindTexture(GL_TEXTURE_2D, _texID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bestWidth, bestHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); // 'w draw all the glyphs SDL_Color fg = { 255, 255, 255, 255 }; int ly = padding; for (int ri = 0; ri < bestRows; ri++) { int lx = padding; for (size_t ci = 0; ci < bestPartition[ri].size(); ci++) { int gi = bestPartition[ri][ci]; SDL_Surface* glyphSurface = TTF_RenderGlyph_Blended(f, (char)(cs + gi), fg); // Pre-multiplication occurs here unsigned char* sp = (unsigned char*)glyphSurface->pixels; int cp = glyphSurface->w * glyphSurface->h * 4; for (int i = 0; i < cp; i += 4) { float a = sp[i + 3] / 255.0f; sp[i] *= a; sp[i + 1] = sp[i]; sp[i + 2] = sp[i]; } // Save glyph image and update coordinates glTexSubImage2D(GL_TEXTURE_2D, 0, lx, bestHeight - ly - 1 - glyphSurface->h, glyphSurface->w, glyphSurface->h, GL_BGRA, GL_UNSIGNED_BYTE, glyphSurface->pixels); glyphRects[gi].x = lx; glyphRects[gi].y = ly; glyphRects[gi].z = glyphSurface->w; glyphRects[gi].w = glyphSurface->h; SDL_FreeSurface(glyphSurface); glyphSurface = nullptr; lx += glyphRects[gi].z + padding; } ly += _fontHeight + padding; } // Draw the unsupported glyph int rs = padding - 1; int* pureWhiteSquare = new int[rs * rs]; memset(pureWhiteSquare, 0xffffffff, rs * rs * sizeof(int)); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rs, rs, GL_RGBA, GL_UNSIGNED_BYTE, pureWhiteSquare); delete[] pureWhiteSquare; pureWhiteSquare = nullptr; // Set some texture parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Create spriteBatch glyphs _glyphs = new CharGlyph[_regLength + 1]; for (i = 0; i < _regLength; i++) { _glyphs[i].character = (char)(cs + i); _glyphs[i].size = glm::vec2(glyphRects[i].z, glyphRects[i].w); _glyphs[i].uvRect = glm::vec4( (float)glyphRects[i].x / (float)bestWidth, (float)glyphRects[i].y / (float)bestHeight, (float)glyphRects[i].z / (float)bestWidth, (float)glyphRects[i].w / (float)bestHeight ); } _glyphs[_regLength].character = ' '; _glyphs[_regLength].size = _glyphs[0].size; _glyphs[_regLength].uvRect = glm::vec4(0, 0, (float)rs / (float)bestWidth, (float)rs / (float)bestHeight); glBindTexture(GL_TEXTURE_2D, 0); delete[] glyphRects; delete[] bestPartition; TTF_CloseFont(f); }
bool Texture::loadFromImage(const Image& image, const IntRect& area) { // Retrieve the image size int width = static_cast<int>(image.getSize().x); int height = static_cast<int>(image.getSize().y); // Load the entire image if the source area is either empty or contains the whole image if (area.width == 0 || (area.height == 0) || ((area.left <= 0) && (area.top <= 0) && (area.width >= width) && (area.height >= height))) { // Load the entire image if (create(image.getSize().x, image.getSize().y)) { update(image); // Force an OpenGL flush, so that the texture will appear updated // in all contexts immediately (solves problems in multi-threaded apps) glCheck(glFlush()); return true; } else { return false; } } else { // Load a sub-area of the image // Adjust the rectangle to the size of the image IntRect rectangle = area; if (rectangle.left < 0) rectangle.left = 0; if (rectangle.top < 0) rectangle.top = 0; if (rectangle.left + rectangle.width > width) rectangle.width = width - rectangle.left; if (rectangle.top + rectangle.height > height) rectangle.height = height - rectangle.top; // Create the texture and upload the pixels if (create(rectangle.width, rectangle.height)) { // Make sure that the current texture binding will be preserved priv::TextureSaver save; // Copy the pixels to the texture, row by row const Uint8* pixels = image.getPixelsPtr() + 4 * (rectangle.left + (width * rectangle.top)); glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); for (int i = 0; i < rectangle.height; ++i) { glCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, i, rectangle.width, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); pixels += 4 * width; } // Force an OpenGL flush, so that the texture will appear updated // in all contexts immediately (solves problems in multi-threaded apps) glCheck(glFlush()); return true; } else { return false; } } }
enum piglit_result test_tex_sub_image(void *null) { GLuint pbs[1]; GLfloat t[TEXSIZE * TEXSIZE * 3]; int i, j; int use_unpack = 0; GLfloat green[3] = { 0.0, 1.0, 0.0 }; GLfloat black[3] = { 0.0, 0.0, 0.0 }; GLfloat *pbo_mem = NULL; GLfloat buf[WINSIZE * WINSIZE * 3]; bool pass = true; GLfloat expected[WINSIZE * WINSIZE * 3]; GLfloat tolerance[4]; piglit_compute_probe_tolerance(GL_RGB, &tolerance[0]); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); for (use_unpack = 0; use_unpack < 2; use_unpack++) { pbo_mem = NULL; glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); if (use_unpack) { glGenBuffersARB(1, pbs); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbs[0]); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, TEXSIZE * TEXSIZE * 3 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_RGB, GL_FLOAT, NULL); if (use_unpack) { glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbs[0]); pbo_mem = (GLfloat *) glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); } else { pbo_mem = t; } for (i = 0; i < TEXSIZE * TEXSIZE; i++) { pbo_mem[3 * i] = 0.0; pbo_mem[3 * i + 1] = 1.0; pbo_mem[3 * i + 2] = 0.0; } if (use_unpack) { glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEXSIZE, TEXSIZE, GL_RGB, GL_FLOAT, NULL); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } else glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEXSIZE, TEXSIZE, GL_RGB, GL_FLOAT, pbo_mem); glEnable(GL_TEXTURE_2D); glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(10, 0); glTexCoord2f(1, 1); glVertex2f(10, 10); glTexCoord2f(0, 1); glVertex2f(0, 10); glEnd(); glDisable(GL_TEXTURE_2D); glReadPixels(0, 0, WINSIZE, WINSIZE, GL_RGB, GL_FLOAT, buf); for (j = 0; j < WINSIZE; j++) { for (i = 0; i < WINSIZE; i++) { int idx = (j * WINSIZE + i) * 3; if (i < 10 && j < 10) { expected[idx + 0] = green[0]; expected[idx + 1] = green[1]; expected[idx + 2] = green[2]; } else { expected[idx + 0] = black[0]; expected[idx + 1] = black[1]; expected[idx + 2] = black[2]; } } } pass &= piglit_compare_images_color(0, 0, WINSIZE, WINSIZE, 3, tolerance, expected, buf); } return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
void VideoSurface::paintGL() { mutex.lock(); VideoFrame currFrame = frame; frame.invalidate(); mutex.unlock(); if (currFrame.isValid() && res != currFrame.resolution) { res = currFrame.resolution; // delete old texture if (textureId != 0) glDeleteTextures(1, &textureId); // a texture used to render the pbo (has the match the pixelformat of the source) glGenTextures(1,&textureId); glBindTexture(GL_TEXTURE_2D, textureId); glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, res.width(), res.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } if (currFrame.isValid()) { pboIndex = (pboIndex + 1) % 2; int nextPboIndex = (pboIndex + 1) % 2; if (pboAllocSize != currFrame.frameData.size()) { qDebug() << "VideoSurface: Resize pbo " << currFrame.frameData.size() << "(" << currFrame.resolution << ")" << "bytes (before" << pboAllocSize << ")"; pbo[0]->bind(); pbo[0]->allocate(currFrame.frameData.size()); pbo[0]->release(); pbo[1]->bind(); pbo[1]->allocate(currFrame.frameData.size()); pbo[1]->release(); pboAllocSize = currFrame.frameData.size(); } pbo[pboIndex]->bind(); glBindTexture(GL_TEXTURE_2D, textureId); glTexSubImage2D(GL_TEXTURE_2D,0,0,0, res.width(), res.height(), GL_RGB, GL_UNSIGNED_BYTE, 0); pbo[pboIndex]->unmap(); pbo[pboIndex]->release(); // transfer data pbo[nextPboIndex]->bind(); void* ptr = pbo[nextPboIndex]->map(QOpenGLBuffer::WriteOnly); if (ptr) memcpy(ptr, currFrame.frameData.data(), currFrame.frameData.size()); pbo[nextPboIndex]->unmap(); pbo[nextPboIndex]->release(); } // background glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); // keep aspect ratio float aspectRatio = float(res.width()) / float(res.height()); if (width() < float(height()) * aspectRatio) { float h = float(width()) / aspectRatio; glViewport(0, (height() - h)*0.5f, width(), h); } else { float w = float(height()) * float(aspectRatio); glViewport((width() - w)*0.5f, 0, w, height()); } QOpenGLShaderProgram* programm = nullptr; switch (frame.format) { case VideoFrame::YUV: programm = yuvProgramm; break; case VideoFrame::BGR: programm = bgrProgramm; break; default: break; } if (programm) { // render pbo static float values[] = { -1, -1, 1, -1, -1, 1, 1, 1 }; programm->bind(); programm->setAttributeArray(0, GL_FLOAT, values, 2); programm->enableAttributeArray(0); } glBindTexture(GL_TEXTURE_2D, textureId); //draw fullscreen quad glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindTexture(GL_TEXTURE_2D, 0); if (programm) { programm->disableAttributeArray(0); programm->release(); } }
//---------------------------------------------------------- void ofTexture::loadData(void * data, int w, int h, int glFormat){ // can we allow for uploads bigger then texture and // just take as much as the texture can? // // ie: // int uploadW = MIN(w, tex_w); // int uploadH = MIN(h, tex_h); // but with a "step" size of w? // check "glTexSubImage2D" texData.glType = glFormat; /*if(glFormat!=texData.glType) { ofLogError() << "ofTexture::loadData() failed to upload format " << ofGetGlInternalFormatName(glFormat) << " data to " << ofGetGlInternalFormatName(texData.glType) << " texture" <<endl; return; }*/ if(w > texData.tex_w || h > texData.tex_h) { ofLogError() << "ofTexture::loadData() failed to upload " << w << "x" << h << " data to " << texData.tex_w << "x" << texData.tex_h << " texture"; return; } // update our size with the new dimensions texData.width = w; texData.height = h; // compute new tex co-ords based on the ratio of data's w, h to texture w,h; #ifndef TARGET_OPENGLES if (texData.textureTarget == GL_TEXTURE_RECTANGLE_ARB){ texData.tex_t = w; texData.tex_u = h; } else #endif { texData.tex_t = (float)(w) / (float)texData.tex_w; texData.tex_u = (float)(h) / (float)texData.tex_h; } // ok this is an ultra annoying bug : // opengl texels and linear filtering - // when we have a sub-image, and we scale it // we can clamp the border pixels to the border, // but the borders of the sub image get mixed with // neighboring pixels... // grr... // // the best solution would be to pad out the image // being uploaded with 2 pixels on all sides, and // recompute tex_t coordinates.. // another option is a gl_arb non pow 2 textures... // the current hack is to alter the tex_t, tex_u calcs, but // that makes the image slightly off... // this is currently being done in draw... // // we need a good solution for this.. // // http://www.opengl.org/discussion_boards/ubb/ultimatebb.php?ubb=get_topic;f=3;t=014770#000001 // http://www.opengl.org/discussion_boards/ubb/ultimatebb.php?ubb=get_topic;f=3;t=014770#000001 //------------------------ likely, we are uploading continuous data GLint prevAlignment; glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevAlignment); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //Sosolimited: texture compression if (texData.compressionType == OF_COMPRESS_NONE) { //STANDARD openFrameworks: no compression //update the texture image: glEnable(texData.textureTarget); glBindTexture(texData.textureTarget, (GLuint) texData.textureID); glTexSubImage2D(texData.textureTarget, 0, 0, 0, w, h, texData.glType, texData.pixelType, data); glDisable(texData.textureTarget); } else { //SOSOLIMITED: setup mipmaps and use compression //TODO: activate at least mimaps for OPENGL_ES //need proper tex_u and tex_t positions, with mipmaps they are the nearest power of 2 #ifndef TARGET_OPENGLES if (texData.textureTarget == GL_TEXTURE_RECTANGLE_ARB){ //need to find closest powers of two int last_h = ofNextPow2(texData.height)>>1; int next_h = ofNextPow2(texData.height); if ((texData.height - last_h) < (next_h - texData.height)) texData.tex_u = last_h; else texData.tex_u = next_h; int last_w = ofNextPow2(texData.width)>>1; int next_w = ofNextPow2(texData.width); if ((texData.width - last_w) < (next_w - texData.width)) texData.tex_t = last_w; else texData.tex_t = next_w; //printf("ofTexture::loadData w:%.1f, h:%.1f, tex_t:%.1f, tex_u:%.1f \n", texData.width,texData.height,texData.tex_t,texData.tex_u); } #endif glEnable(texData.textureTarget); glBindTexture(texData.textureTarget, (GLuint)texData.textureID); glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifndef TARGET_OPENGLES glTexParameteri(texData.textureTarget, GL_GENERATE_MIPMAP_SGIS, true); #endif glTexParameteri( texData.textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri( texData.textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri( texData.textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri( texData.textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2); #ifndef TARGET_OPENGLES //using sRGB compression if (texData.compressionType == OF_COMPRESS_SRGB) { if(texData.glType == GL_RGBA) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_SRGB_ALPHA, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_RGB) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_SRGB_ALPHA, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_LUMINANCE_ALPHA) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_SRGB_ALPHA, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_LUMINANCE) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_SRGB_ALPHA, w, h, texData.glType, texData.pixelType, data); } //using ARB compression: default else { if(texData.glType == GL_RGBA) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_RGBA_ARB, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_RGB) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_RGB_ARB, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_LUMINANCE_ALPHA) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_LUMINANCE_ALPHA_ARB, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_LUMINANCE) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_LUMINANCE_ARB, w, h, texData.glType, texData.pixelType, data); } #endif glDisable(texData.textureTarget); }
static void draw_tex(gl1_t *gl1, int pot_width, int pot_height, int width, int height, GLuint tex, const void *frame_to_copy) { /* FIXME: For now, everything is uploaded as BGRA8888, I could not get 444 or 555 to work, and there is no 565 support in GL 1.1 either. */ GLint internalFormat = GL_RGBA8; GLenum format = (gl1->supports_bgra ? GL_BGRA_EXT : GL_RGBA); GLenum type = GL_UNSIGNED_BYTE; glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_STENCIL_TEST); glDisable(GL_SCISSOR_TEST); glEnable(GL_TEXTURE_2D); /* multi-texture not part of GL 1.1 */ /*glActiveTexture(GL_TEXTURE0);*/ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, pot_width); glBindTexture(GL_TEXTURE_2D, tex); /* TODO: We could implement red/blue swap if client GL does not support BGRA... but even MS GDI Generic supports it */ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, pot_width, pot_height, 0, format, type, NULL); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, frame_to_copy); if (tex == gl1->tex) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (gl1->smooth ? GL_LINEAR : GL_NEAREST)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (gl1->smooth ? GL_LINEAR : GL_NEAREST)); } else if (tex == gl1->menu_tex) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (gl1->menu_smooth ? GL_LINEAR : GL_NEAREST)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (gl1->menu_smooth ? GL_LINEAR : GL_NEAREST)); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); /* stock coord set does not handle POT, disable for now */ /*glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glColorPointer(4, GL_FLOAT, 0, gl1->coords.color); glVertexPointer(2, GL_FLOAT, 0, gl1->coords.vertex); glTexCoordPointer(2, GL_FLOAT, 0, gl1->coords.tex_coord); glDrawArrays(GL_TRIANGLES, 0, gl1->coords.vertices); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY);*/ if (gl1->rotation && tex == gl1->tex) glRotatef(gl1->rotation, 0.0f, 0.0f, 1.0f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); { float tex_BL[2] = {0.0f, 0.0f}; float tex_BR[2] = {1.0f, 0.0f}; float tex_TL[2] = {0.0f, 1.0f}; float tex_TR[2] = {1.0f, 1.0f}; float *tex_mirror_BL = tex_TL; float *tex_mirror_BR = tex_TR; float *tex_mirror_TL = tex_BL; float *tex_mirror_TR = tex_BR; float norm_width = (1.0f / (float)pot_width) * (float)width; float norm_height = (1.0f / (float)pot_height) * (float)height; /* remove extra POT padding */ tex_mirror_BR[0] = norm_width; tex_mirror_TR[0] = norm_width; /* normally this would be 1.0 - height, but we're drawing upside-down */ tex_mirror_BL[1] = norm_height; tex_mirror_BR[1] = norm_height; glTexCoord2f(tex_mirror_BL[0], tex_mirror_BL[1]); glVertex2f(-1.0f, -1.0f); glTexCoord2f(tex_mirror_TL[0], tex_mirror_TL[1]); glVertex2f(-1.0f, 1.0f); glTexCoord2f(tex_mirror_TR[0], tex_mirror_TR[1]); glVertex2f(1.0f, 1.0f); glTexCoord2f(tex_mirror_BR[0], tex_mirror_BR[1]); glVertex2f(1.0f, -1.0f); } glEnd(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); }
void display() { mMediaSource->idle(); // Check whether the texture needs to be recreated. if(mMediaSource->textureValid()) { if( (mAppTextureWidth != mMediaSource->getTextureWidth() || mAppTextureHeight != mMediaSource->getTextureHeight()) && (mAppWindowWidth == mMediaSource->getWidth() && mAppWindowHeight == mMediaSource->getHeight()) ) { // Attempt to (re)create the texture createTexture(); } } // clear screen glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); if(mAppTexture != 0) { // use the browser texture glBindTexture( GL_TEXTURE_2D, mAppTexture ); // If dirty, update the texture. LLRect dirtyRect; if(!mMediaSource->textureValid()) { // LL_DEBUGS("media_plugin_test") << "Resize in progress, skipping update..." << LL_ENDL; } else if(mAppWindowWidth != mMediaSource->getWidth() || mAppWindowHeight != mMediaSource->getHeight()) { // A resize is in progress. Just wait for it... } else if(mMediaSource->getDirty(&dirtyRect)) { // grab the page const unsigned char* pixels = mMediaSource->getBitsData(); if ( pixels ) { // write them into the texture // Paranoia: intersect dirtyRect with (0, 0, mAppTextureWidth, mAppTextureHeight)? int x_offset = dirtyRect.mLeft; int y_offset = dirtyRect.mBottom; int width = dirtyRect.mRight - dirtyRect.mLeft; int height = dirtyRect.mTop - dirtyRect.mBottom; LL_DEBUGS("media_plugin_test") << "Updating, dirty rect is (" << dirtyRect.mLeft << ", " << dirtyRect.mTop << ", " << dirtyRect.mRight << ", " << dirtyRect.mBottom << "), update params are: (" << x_offset << ", " << y_offset << ", " << width << ", " << height << ")" << LL_ENDL; // Offset the pixels pointer properly pixels += (y_offset * mMediaSource->getTextureDepth() * mMediaSource->getTextureWidth()); pixels += (x_offset * mMediaSource->getTextureDepth()); glPixelStorei(GL_UNPACK_ROW_LENGTH, mMediaSource->getTextureWidth()); glTexSubImage2D( GL_TEXTURE_2D, 0, x_offset, y_offset, width, height, mMediaSource->getTextureFormatPrimary(), mMediaSource->getTextureFormatType(), pixels ); mMediaSource->resetDirty(); } } // scale the texture so that it fits the screen GLdouble media_texture_x = mAppWindowWidth / (double)mAppTextureWidth; GLdouble media_texture_y = mAppWindowHeight / (double)mAppTextureHeight; // draw the single quad full screen (orthographic) glEnable( GL_TEXTURE_2D ); glColor3f( 1.0f, 1.0f, 1.0f ); glBegin( GL_QUADS ); if(mAppTextureCoordsOpenGL) { // Render the texture as per opengl coords (where 0,0 is at the lower left) glTexCoord2d( 0, 0 ); glVertex2d( 0, 0 ); glTexCoord2d( 0 , media_texture_y ); glVertex2d( 0, mAppWindowHeight); glTexCoord2d( media_texture_x, media_texture_y ); glVertex2d( mAppWindowWidth , mAppWindowHeight); glTexCoord2d( media_texture_x, 0 ); glVertex2d( mAppWindowWidth, 0 ); } else { // Render the texture the "other way round" (where 0,0 is at the upper left) glTexCoord2d( 0, media_texture_y ); glVertex2d( 0, 0 ); glTexCoord2d( 0 , 0 ); glVertex2d( 0, mAppWindowHeight); glTexCoord2d( media_texture_x, 0 ); glVertex2d( mAppWindowWidth , mAppWindowHeight); glTexCoord2d( media_texture_x, media_texture_y ); glVertex2d( mAppWindowWidth, 0 ); } glEnd(); } glutSwapBuffers(); };
void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoff, GC3Dint yoff, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels) { makeContextCurrent(); glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); }