/** * Bilinear interpolation of two source rows. * GLubyte pixels. */ static void resample_linear_row_ub(GLint srcWidth, GLint dstWidth, const GLvoid *srcBuffer0, const GLvoid *srcBuffer1, GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight) { const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0; const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1; GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer; const GLfloat dstWidthF = (GLfloat) dstWidth; GLint dstCol; for (dstCol = 0; dstCol < dstWidth; dstCol++) { const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF; GLint srcCol0 = IFLOOR(srcCol); GLint srcCol1 = srcCol0 + 1; GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */ GLfloat red, green, blue, alpha; ASSERT(srcCol0 >= 0); ASSERT(srcCol0 < srcWidth); ASSERT(srcCol1 <= srcWidth); if (srcCol1 == srcWidth) { /* last column fudge */ srcCol1--; colWeight = 0.0; } if (flip) { srcCol0 = srcWidth - 1 - srcCol0; srcCol1 = srcWidth - 1 - srcCol1; } red = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP], srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]); green = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP], srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]); blue = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP], srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]); alpha = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP], srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]); dstColor[dstCol][RCOMP] = IFLOOR(red); dstColor[dstCol][GCOMP] = IFLOOR(green); dstColor[dstCol][BCOMP] = IFLOOR(blue); dstColor[dstCol][ACOMP] = IFLOOR(alpha); } }
void _mesa_Bitmap( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" ); return; } if (ctx->Current.RasterPosValid == GL_FALSE) { return; /* do nothing */ } if (ctx->RenderMode==GL_RENDER) { if (bitmap) { /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */ GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig); GLint y = IFLOOR(ctx->Current.RasterPos[1] - yorig); if (ctx->NewState) { _mesa_update_state(ctx); } ctx->OcclusionResult = GL_TRUE; ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap ); } } else if (ctx->RenderMode==GL_FEEDBACK) { if (ctx->Current.RasterPosValid) { FLUSH_CURRENT(ctx, 0); FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterIndex, ctx->Current.RasterTexCoord ); } } else if (ctx->RenderMode==GL_SELECT) { /* Bitmaps don't generate selection hits. See appendix B of 1.1 spec. */ } /* update raster position */ ctx->Current.RasterPos[0] += xmove; ctx->Current.RasterPos[1] += ymove; }
/** * Bilinear interpolation of two source rows. floating point pixels. */ static void resample_linear_row_float(GLint srcWidth, GLint dstWidth, const GLvoid *srcBuffer0, const GLvoid *srcBuffer1, GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight) { const GLfloat (*srcColor0)[4] = (const GLfloat (*)[4]) srcBuffer0; const GLfloat (*srcColor1)[4] = (const GLfloat (*)[4]) srcBuffer1; GLfloat (*dstColor)[4] = (GLfloat (*)[4]) dstBuffer; GLint dstCol; for (dstCol = 0; dstCol < dstWidth; dstCol++) { const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F; GLint srcCol0 = MAX2(0, IFLOOR(srcCol)); GLint srcCol1 = srcCol0 + 1; GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */ GLfloat red, green, blue, alpha; assert(srcCol0 < srcWidth); assert(srcCol1 <= srcWidth); if (srcCol1 == srcWidth) { /* last column fudge */ srcCol1--; colWeight = 0.0; } if (flip) { srcCol0 = srcWidth - 1 - srcCol0; srcCol1 = srcWidth - 1 - srcCol1; } red = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP], srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]); green = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP], srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]); blue = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP], srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]); alpha = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP], srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]); dstColor[dstCol][RCOMP] = red; dstColor[dstCol][GCOMP] = green; dstColor[dstCol][BCOMP] = blue; dstColor[dstCol][ACOMP] = alpha; } }
int warpRecFromTetPerspRgb (ppf dst, ppf src, int dX, int dY, unt dW, unt dH , pDmj sD, float sQ[4][2]) { float sx0 = sQ[0][0], sx1 = sQ[1][0], sx2 = sQ[2][0], sx3 = sQ[3][0]; float sy0 = sQ[0][1], sy1 = sQ[1][1], sy2 = sQ[2][1], sy3 = sQ[3][1]; float x21 = sx2 - sx1, x32 = sx3 - sx2; float y21 = sy2 - sy1, y32 = sy3 - sy2; float x44 = sx0 - sx1 + sx2 - sx3; float y44 = sy0 - sy1 + sy2 - sy3; #if 0 /* AFFINE: for SPECIAL CASE OF x44 == 0 && y44 == 0 */ float x10 = sx1 - sx0, y10 = sy1 - sy0; float a11 = x10, a12 = y10, a13 = 0.0; float a21 = x21, a22 = y21, a23 = 0.0; float a31 = sx0, a32 = sy0, a33 = 1.0; #else /* PERSPECIVE/PROJECTIVE: YES */ float det = (y21*x32 - x21*y32); float a13 = (x44*y32 - y44*x32)/det; float a23 = (y21*x44 - x21*y44)/det; float a33 = 1.0F; float a31 = sx0; float a32 = sy0; float a11 = (1.0F + a13)*sx1 - a31; float a21 = (1.0F + a23)*sx3 - a31; float a12 = (1.0F + a13)*sy1 - a32; float a22 = (1.0F + a23)*sy3 - a32; #endif double fx,fy,fw,fh, mx,my,mw,mh, xx, yy, ww, fL,fM,fN,fO; pfl dp, sp; float sWm = sD->w - 1.3333, sHm = sD->h - 1.3333; int k, j, ks, js, sM = sD->w * 3, sP = sM + 3; for ( j = 0; j < dH; j++) { /* GO BY HALF-INTEGER INCREMENTS?? @@ */ fh = (dbl) j / dH; mh = 1.0F - fh; dp = dst[j + dY] + dX*3; for (k = 0; k < dW; k++) { fw = (dbl)k / dW; mw = 1.0F - fw; ww = (a13*fw + a23*fh + a33); xx = (a11*fw + a21*fh + a31)/ww; yy = (a12*fw + a22*fh + a32)/ww; /* if(!(++cnt%711)) printf("wPTB %3d %3d: % 7.3f % 7.3f (%7.3f)\n",j,k,xx,yy,ww); */ if (xx < 0.0) xx = 0.3333; else if (xx >= sWm) xx = sWm; if (yy < 0.0) yy = 0.3333; else if (yy >= sHm) yy = sHm; js = IFLOOR(yy); fy = yy - js; my = 1.0F - fy; ks = IFLOOR(xx); fx = xx - ks; mx = 1.0F - fx; sp = src[js] + ks*3; fL = mx*my; fM = fx*my; fN = mx*fy; fO = fx*fy; *dp++ = fL*sp[0] + fM*sp[3] + fN*sp[sM] + fO*sp[sP]; sp++; *dp++ = fL*sp[0] + fM*sp[3] + fN*sp[sM] + fO*sp[sP]; sp++; *dp++ = fL*sp[0] + fM*sp[3] + fN*sp[sM] + fO*sp[sP]; } } /*********************************************************** printf("warpRecFromTetPerspRgb [a]:\n\ \t% 14.3f\t% 14.3f\t% 14.3f\n", a11, a12, a13); printf("\ \t% 14.3f\t% 14.3f\t% 14.3f\n", a21, a22, a23); printf("\ \t% 14.3f\t% 14.3f\t% 14.3f\n", a31, a32, a33); ************************************************************/ return 0; }
/** * Bilinear filtered blit (color only). */ static void blit_linear(struct gl_context *ctx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) { struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer; struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0]; const GLint srcWidth = ABS(srcX1 - srcX0); const GLint dstWidth = ABS(dstX1 - dstX0); const GLint srcHeight = ABS(srcY1 - srcY0); const GLint dstHeight = ABS(dstY1 - dstY0); const GLfloat dstHeightF = (GLfloat) dstHeight; const GLint srcXpos = MIN2(srcX0, srcX1); const GLint srcYpos = MIN2(srcY0, srcY1); const GLint dstXpos = MIN2(dstX0, dstX1); const GLint dstYpos = MIN2(dstY0, dstY1); const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0); const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0); GLint dstRow; GLint pixelSize; GLvoid *srcBuffer0, *srcBuffer1; GLint srcBufferY0 = -1, srcBufferY1 = -1; GLvoid *dstBuffer; switch (readRb->DataType) { case GL_UNSIGNED_BYTE: pixelSize = 4 * sizeof(GLubyte); break; case GL_UNSIGNED_SHORT: pixelSize = 4 * sizeof(GLushort); break; case GL_UNSIGNED_INT: pixelSize = 4 * sizeof(GLuint); break; case GL_FLOAT: pixelSize = 4 * sizeof(GLfloat); break; default: _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest", readRb->DataType); return; } /* Allocate the src/dst row buffers. * Keep two adjacent src rows around for bilinear sampling. */ srcBuffer0 = malloc(pixelSize * srcWidth); if (!srcBuffer0) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); return; } srcBuffer1 = malloc(pixelSize * srcWidth); if (!srcBuffer1) { free(srcBuffer0); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); return; } dstBuffer = malloc(pixelSize * dstWidth); if (!dstBuffer) { free(srcBuffer0); free(srcBuffer1); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); return; } for (dstRow = 0; dstRow < dstHeight; dstRow++) { const GLint dstY = dstYpos + dstRow; const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF; GLint srcRow0 = IFLOOR(srcRow); GLint srcRow1 = srcRow0 + 1; GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */ ASSERT(srcRow >= 0); ASSERT(srcRow < srcHeight); if (srcRow1 == srcHeight) { /* last row fudge */ srcRow1 = srcRow0; rowWeight = 0.0; } if (invertY) { srcRow0 = srcHeight - 1 - srcRow0; srcRow1 = srcHeight - 1 - srcRow1; } srcY0 = srcYpos + srcRow0; srcY1 = srcYpos + srcRow1; /* get the two source rows */ if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) { /* use same source row buffers again */ } else if (srcY0 == srcBufferY1) { /* move buffer1 into buffer0 by swapping pointers */ GLvoid *tmp = srcBuffer0; srcBuffer0 = srcBuffer1; srcBuffer1 = tmp; /* get y1 row */ readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1); srcBufferY0 = srcY0; srcBufferY1 = srcY1; } else { /* get both new rows */ readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0, srcBuffer0); readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1); srcBufferY0 = srcY0; srcBufferY1 = srcY1; } if (readRb->DataType == GL_UNSIGNED_BYTE) { resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1, dstBuffer, invertX, rowWeight); } else { _mesa_problem(ctx, "Unsupported color channel type in sw blit"); break; } /* store pixel row in destination */ drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL); } free(srcBuffer0); free(srcBuffer1); free(dstBuffer); }
static void GLAPIENTRY _mesa_Bitmap( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" ); return; } if (!ctx->Current.RasterPosValid) { return; /* do nothing */ } /* Note: this call does state validation */ if (!_mesa_valid_to_render(ctx, "glBitmap")) { /* the error code was recorded */ return; } if (ctx->RasterDiscard) return; if (ctx->RenderMode == GL_RENDER) { /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */ if (width > 0 && height > 0) { const GLfloat epsilon = 0.0001F; GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig); GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig); if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* unpack from PBO */ if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, GL_COLOR_INDEX, GL_BITMAP, INT_MAX, (const GLvoid *) bitmap)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(invalid PBO access)"); return; } if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)"); return; } } ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap ); } } #if _HAVE_FULL_GL else if (ctx->RenderMode == GL_FEEDBACK) { FLUSH_CURRENT(ctx, 0); _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } #endif /* update raster position */ ctx->Current.RasterPos[0] += xmove; ctx->Current.RasterPos[1] += ymove; if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
/** * Called via ctx->Driver.DrawAtlasBitmap() */ static void st_DrawAtlasBitmaps(struct gl_context *ctx, const struct gl_bitmap_atlas *atlas, GLuint count, const GLubyte *ids) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_texture_object *stObj = st_texture_object(atlas->texObj); struct pipe_sampler_view *sv; /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ const float z = ctx->Current.RasterPos[2] * 2.0f - 1.0f; const float *color = ctx->Current.RasterColor; const float clip_x_scale = 2.0f / st->state.framebuffer.width; const float clip_y_scale = 2.0f / st->state.framebuffer.height; const unsigned num_verts = count * 4; const unsigned num_vert_bytes = num_verts * sizeof(struct st_util_vertex); struct st_util_vertex *verts; struct pipe_vertex_buffer vb = {0}; unsigned i; if (!st->bitmap.cache) { init_bitmap_state(st); } st_flush_bitmap_cache(st); st_validate_state(st, ST_PIPELINE_RENDER); st_invalidate_readpix_cache(st); sv = st_create_texture_sampler_view(pipe, stObj->pt); if (!sv) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCallLists(bitmap text)"); return; } setup_render_state(ctx, sv, color, true); vb.stride = sizeof(struct st_util_vertex); u_upload_alloc(st->uploader, 0, num_vert_bytes, 4, &vb.buffer_offset, &vb.buffer, (void **) &verts); /* build quads vertex data */ for (i = 0; i < count; i++) { const GLfloat epsilon = 0.0001F; const struct gl_bitmap_glyph *g = &atlas->glyphs[ids[i]]; const float xmove = g->xmove, ymove = g->ymove; const float xorig = g->xorig, yorig = g->yorig; const float s0 = g->x, t0 = g->y; const float s1 = s0 + g->w, t1 = t0 + g->h; const float x0 = IFLOOR(ctx->Current.RasterPos[0] - xorig + epsilon); const float y0 = IFLOOR(ctx->Current.RasterPos[1] - yorig + epsilon); const float x1 = x0 + g->w, y1 = y0 + g->h; const float clip_x0 = x0 * clip_x_scale - 1.0f; const float clip_y0 = y0 * clip_y_scale - 1.0f; const float clip_x1 = x1 * clip_x_scale - 1.0f; const float clip_y1 = y1 * clip_y_scale - 1.0f; /* lower-left corner */ verts->x = clip_x0; verts->y = clip_y0; verts->z = z; verts->r = color[0]; verts->g = color[1]; verts->b = color[2]; verts->a = color[3]; verts->s = s0; verts->t = t0; verts++; /* lower-right corner */ verts->x = clip_x1; verts->y = clip_y0; verts->z = z; verts->r = color[0]; verts->g = color[1]; verts->b = color[2]; verts->a = color[3]; verts->s = s1; verts->t = t0; verts++; /* upper-right corner */ verts->x = clip_x1; verts->y = clip_y1; verts->z = z; verts->r = color[0]; verts->g = color[1]; verts->b = color[2]; verts->a = color[3]; verts->s = s1; verts->t = t1; verts++; /* upper-left corner */ verts->x = clip_x0; verts->y = clip_y1; verts->z = z; verts->r = color[0]; verts->g = color[1]; verts->b = color[2]; verts->a = color[3]; verts->s = s0; verts->t = t1; verts++; /* Update the raster position */ ctx->Current.RasterPos[0] += xmove; ctx->Current.RasterPos[1] += ymove; } u_upload_unmap(st->uploader); cso_set_vertex_buffers(st->cso_context, cso_get_aux_vertex_buffer_slot(st->cso_context), 1, &vb); cso_draw_arrays(st->cso_context, PIPE_PRIM_QUADS, 0, num_verts); restore_render_state(ctx); pipe_resource_reference(&vb.buffer, NULL); pipe_sampler_view_reference(&sv, NULL); /* We uploaded modified constants, need to invalidate them. */ st->dirty |= ST_NEW_FS_CONSTANTS; }
static void GLAPIENTRY _mesa_Bitmap( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" ); return; } if (!ctx->Current.RasterPosValid) { return; /* do nothing */ } if (ctx->NewState) { _mesa_update_state(ctx); } if (!valid_fragment_program(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap (invalid fragment program)"); return; } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glBitmap(incomplete framebuffer)"); return; } if (ctx->RenderMode == GL_RENDER) { /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */ if (width > 0 && height > 0) { const GLfloat epsilon = 0.0001F; GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig); GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig); if (ctx->Unpack.BufferObj->Name) { /* unpack from PBO */ if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, GL_COLOR_INDEX, GL_BITMAP, (GLvoid *) bitmap)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(invalid PBO access)"); return; } if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)"); return; } } ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap ); } } #if _HAVE_FULL_GL else if (ctx->RenderMode == GL_FEEDBACK) { FLUSH_CURRENT(ctx, 0); _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterIndex, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } #endif /* update raster position */ ctx->Current.RasterPos[0] += xmove; ctx->Current.RasterPos[1] += ymove; }
void GLAPIENTRY _mesa_Bitmap( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" ); return; } if (!ctx->Current.RasterPosValid) { return; /* do nothing */ } if (ctx->NewState) { _mesa_update_state(ctx); } if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap (invalid fragment program)"); return; } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glBitmap(incomplete framebuffer)"); return; } if (ctx->RenderMode == GL_RENDER) { if (bitmap) { /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */ GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig); GLint y = IFLOOR(ctx->Current.RasterPos[1] - yorig); ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap ); } } #if _HAVE_FULL_GL else if (ctx->RenderMode == GL_FEEDBACK) { FLUSH_CURRENT(ctx, 0); FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterIndex, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } #endif /* update raster position */ ctx->Current.RasterPos[0] += xmove; ctx->Current.RasterPos[1] += ymove; }
/** * Bilinear filtered blit (color only, non-integer values). */ static void blit_linear(struct gl_context *ctx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) { struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer; struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0]; const GLint srcWidth = ABS(srcX1 - srcX0); const GLint dstWidth = ABS(dstX1 - dstX0); const GLint srcHeight = ABS(srcY1 - srcY0); const GLint dstHeight = ABS(dstY1 - dstY0); const GLfloat dstHeightF = (GLfloat) dstHeight; const GLint srcXpos = MIN2(srcX0, srcX1); const GLint srcYpos = MIN2(srcY0, srcY1); const GLint dstXpos = MIN2(dstX0, dstX1); const GLint dstYpos = MIN2(dstY0, dstY1); const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0); const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0); GLint dstRow; GLint pixelSize; GLvoid *srcBuffer0, *srcBuffer1; GLint srcBufferY0 = -1, srcBufferY1 = -1; GLvoid *dstBuffer; gl_format readFormat = _mesa_get_srgb_format_linear(readRb->Format); gl_format drawFormat = _mesa_get_srgb_format_linear(drawRb->Format); GLuint bpp = _mesa_get_format_bytes(readFormat); GLenum pixelType; GLubyte *srcMap, *dstMap; GLint srcRowStride, dstRowStride; /* Determine datatype for resampling */ if (_mesa_get_format_max_bits(readFormat) == 8 && _mesa_get_format_datatype(readFormat) == GL_UNSIGNED_NORMALIZED) { pixelType = GL_UNSIGNED_BYTE; pixelSize = 4 * sizeof(GLubyte); } else { pixelType = GL_FLOAT; pixelSize = 4 * sizeof(GLfloat); } /* Allocate the src/dst row buffers. * Keep two adjacent src rows around for bilinear sampling. */ srcBuffer0 = malloc(pixelSize * srcWidth); if (!srcBuffer0) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); return; } srcBuffer1 = malloc(pixelSize * srcWidth); if (!srcBuffer1) { free(srcBuffer0); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); return; } dstBuffer = malloc(pixelSize * dstWidth); if (!dstBuffer) { free(srcBuffer0); free(srcBuffer1); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); return; } /* * Map src / dst renderbuffers */ if (readRb == drawRb) { /* map whole buffer for read/write */ ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0, readRb->Width, readRb->Height, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, &srcMap, &srcRowStride); if (!srcMap) { free(srcBuffer0); free(srcBuffer1); free(dstBuffer); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); return; } dstMap = srcMap; dstRowStride = srcRowStride; } else { /* different src/dst buffers */ /* XXX with a bit of work we could just map the regions to be * read/written instead of the whole buffers. */ ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0, readRb->Width, readRb->Height, GL_MAP_READ_BIT, &srcMap, &srcRowStride); if (!srcMap) { free(srcBuffer0); free(srcBuffer1); free(dstBuffer); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); return; } ctx->Driver.MapRenderbuffer(ctx, drawRb, 0, 0, drawRb->Width, drawRb->Height, GL_MAP_WRITE_BIT, &dstMap, &dstRowStride); if (!dstMap) { ctx->Driver.UnmapRenderbuffer(ctx, readRb); free(srcBuffer0); free(srcBuffer1); free(dstBuffer); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); return; } } for (dstRow = 0; dstRow < dstHeight; dstRow++) { const GLint dstY = dstYpos + dstRow; const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF; GLint srcRow0 = IFLOOR(srcRow); GLint srcRow1 = srcRow0 + 1; GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */ ASSERT(srcRow >= 0); ASSERT(srcRow < srcHeight); if (srcRow1 == srcHeight) { /* last row fudge */ srcRow1 = srcRow0; rowWeight = 0.0; } if (invertY) { srcRow0 = srcHeight - 1 - srcRow0; srcRow1 = srcHeight - 1 - srcRow1; } srcY0 = srcYpos + srcRow0; srcY1 = srcYpos + srcRow1; /* get the two source rows */ if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) { /* use same source row buffers again */ } else if (srcY0 == srcBufferY1) { /* move buffer1 into buffer0 by swapping pointers */ GLvoid *tmp = srcBuffer0; srcBuffer0 = srcBuffer1; srcBuffer1 = tmp; /* get y1 row */ { GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp; if (pixelType == GL_UNSIGNED_BYTE) { _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth, src, srcBuffer1); } else { _mesa_unpack_rgba_row(readFormat, srcWidth, src, srcBuffer1); } } srcBufferY0 = srcY0; srcBufferY1 = srcY1; } else { /* get both new rows */ { GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp; GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp; if (pixelType == GL_UNSIGNED_BYTE) { _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth, src0, srcBuffer0); _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth, src1, srcBuffer1); } else { _mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0); _mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1); } } srcBufferY0 = srcY0; srcBufferY1 = srcY1; } if (pixelType == GL_UNSIGNED_BYTE) { resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1, dstBuffer, invertX, rowWeight); } else { resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1, dstBuffer, invertX, rowWeight); } /* store pixel row in destination */ { GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp; if (pixelType == GL_UNSIGNED_BYTE) { _mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst); } else { _mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst); } } } free(srcBuffer0); free(srcBuffer1); free(dstBuffer); ctx->Driver.UnmapRenderbuffer(ctx, readRb); if (drawRb != readRb) { ctx->Driver.UnmapRenderbuffer(ctx, drawRb); } }
void fxyQuadFwdSpatBil ( ppf dst, ppf wts, ppf qxyB, ppf qxyC , ppf pre0, ppf pre1, ppf pre2, unt dW, unt dH, dbl trans) { unt j, k; int kT, jT, wM = dW-1, hM = dH-1; pfl pB, pC, p0, p1, p2; flt xT, yT, xM, yM, dV; flt trs = (flt) trans; flt tr2 = (flt)(trans*trans); flt w0 = (flt)(1.0 - trs*2.0 + tr2); flt w1 = (flt)((trs - tr2)*2.0); flt w2 = tr2; flt wT = w0 + w1 + w2; w0 /= wT; w1 /= wT; w2 /= wT; dV = w0 + w1 + w2; #if 1 /**************************************/ dV -= 1.0; if (dV < 0.0) dV = -dV; assert(dV < 0.001); #else /**************************************/ if (trans < 0.5) w1 = 2.0*trans, w0 = 1.0 - w1, w2 = 0.0; else w2 = 2.0*trans-1.0, w1 = 1.0 - w2, w0 = 0.0; #endif /**************************************/ rowZeroF(dst,0,0,dW,dH); rowZeroF(wts,0,0,dW,dH); for (j = 0; j < dH; j++) { pB = *qxyB++ ; pC = *qxyC++ ; p0 = *pre0++ ; p1 = *pre1++ ; p2 = *pre2++; for (k = 0; k < dW; k++) { xT = k + trs * *pB++ + tr2 * *pC++; kT = IFLOOR(xT); if (0 <= kT && kT < wM) { yT = j + trs * *pB++ + tr2 * *pC++; jT = IFLOOR(yT); if (0 <= jT && jT < hM) { xT -= kT; xM = 1.0F - xT; yT -= jT; yM = 1.0F - yT; dV = w0**p0++ + w1**p1++ + w2**p2++; wT = xM*yM; wts[jT][kT] += wT; dst[jT][kT] += wT*dV; kT++; wT = xT*yM; wts[jT][kT] += wT; dst[jT][kT] += wT*dV; jT++; wT = xT*yT; wts[jT][kT] += wT; dst[jT][kT] += wT*dV; kT--; wT = xM*yT; wts[jT][kT] += wT; dst[jT][kT] += wT*dV; } else { p0++; p1++; p2++; } } else { p0++; p1++; p2++; pB++; pC++; } } } }