void r300SetupVertexProgram(r300ContextPtr rmesa) { GLcontext *ctx = rmesa->radeon.glCtx; struct r300_vertex_program *prog = rmesa->selected_vp; int inst_count = 0; int param_count = 0; /* Reset state, in case we don't use something */ ((drm_r300_cmd_header_t *) rmesa->hw.vpp.cmd)->vpu.count = 0; ((drm_r300_cmd_header_t *) rmesa->hw.vpi.cmd)->vpu.count = 0; ((drm_r300_cmd_header_t *) rmesa->hw.vps.cmd)->vpu.count = 0; R300_STATECHANGE(rmesa, vap_flush); R300_STATECHANGE(rmesa, vpp); param_count = r300VertexProgUpdateParams(ctx, prog, (float *)&rmesa->hw.vpp.cmd[R300_VPP_PARAM_0]); bump_vpu_count(rmesa->hw.vpp.cmd, param_count); param_count /= 4; r300EmitVertexProgram(rmesa, R300_PVS_CODE_START, &(prog->code)); inst_count = (prog->code.length / 4) - 1; r300VapCntl(rmesa, _mesa_bitcount(prog->code.InputsRead), _mesa_bitcount(prog->code.OutputsWritten), prog->code.num_temporaries); R300_STATECHANGE(rmesa, pvs); rmesa->hw.pvs.cmd[R300_PVS_CNTL_1] = (0 << R300_PVS_FIRST_INST_SHIFT) | (inst_count << R300_PVS_XYZW_VALID_INST_SHIFT) | (inst_count << R300_PVS_LAST_INST_SHIFT); rmesa->hw.pvs.cmd[R300_PVS_CNTL_2] = (0 << R300_PVS_CONST_BASE_OFFSET_SHIFT) | (param_count << R300_PVS_MAX_CONST_ADDR_SHIFT); rmesa->hw.pvs.cmd[R300_PVS_CNTL_3] = (inst_count << R300_PVS_LAST_VTX_SRC_INST_SHIFT); }
/** * For GLX_EXT_texture_from_pixmap */ XMesaBuffer XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap, int format, int target, int mipmap) { GET_CURRENT_CONTEXT(ctx); XMesaBuffer b; GLuint width, height; assert(v); b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap); if (!b) return NULL; /* get pixmap size, update framebuffer/renderbuffer dims */ xmesa_get_window_size(v->display, b, &width, &height); _mesa_resize_framebuffer(NULL, &(b->mesa_buffer), width, height); if (target == 0) { /* examine dims */ if (ctx->Extensions.ARB_texture_non_power_of_two) { target = GLX_TEXTURE_2D_EXT; } else if ( _mesa_bitcount(width) == 1 && _mesa_bitcount(height) == 1) { /* power of two size */ if (height == 1) { target = GLX_TEXTURE_1D_EXT; } else { target = GLX_TEXTURE_2D_EXT; } } else if (ctx->Extensions.NV_texture_rectangle) { target = GLX_TEXTURE_RECTANGLE_EXT; } else { /* non power of two textures not supported */ XMesaDestroyBuffer(b); return 0; } } b->TextureTarget = target; b->TextureFormat = format; b->TextureMipmap = mipmap; if (!initialize_visual_and_buffer(v, b, (XMesaDrawable) p, cmap)) { xmesa_free_buffer(b); return NULL; } return b; }
void GLAPIENTRY _mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */ if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) { _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" ); return; } if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) { /* test that mapsize is a power of two */ if (_mesa_bitcount((GLuint) mapsize) != 1) { _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" ); return; } } FLUSH_VERTICES(ctx, _NEW_PIXEL); if (ctx->Unpack.BufferObj->Name) { /* unpack pixelmap from PBO */ GLubyte *buf; /* Note, need to use DefaultPacking and Unpack's buffer object */ ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj; if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1, GL_INTENSITY, GL_FLOAT, values)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glPixelMapfv(invalid PBO access)"); return; } /* restore */ ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj; buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, GL_READ_ONLY_ARB, ctx->Unpack.BufferObj); if (!buf) { /* buffer is already mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glPixelMapfv(PBO is mapped)"); return; } values = (const GLfloat *) ADD_POINTERS(buf, values); } else if (!values) { return; } store_pixelmap(ctx, map, mapsize, values); if (ctx->Unpack.BufferObj->Name) { ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, ctx->Unpack.BufferObj); } }
/** * Parse a texture image source: * [TEX0 | TEX1 | .. | TEX15] , [1D | 2D | 3D | CUBE | RECT] */ static GLboolean Parse_TextureImageId(struct parse_state *parseState, GLubyte *texUnit, GLubyte *texTargetBit) { GLubyte imageSrc[100]; GLint unit; if (!Parse_Token(parseState, imageSrc)) RETURN_ERROR; if (imageSrc[0] != 'T' || imageSrc[1] != 'E' || imageSrc[2] != 'X') { RETURN_ERROR1("Expected TEX# source"); } unit = atoi((const char *) imageSrc + 3); if ((unit < 0 || unit > MAX_TEXTURE_IMAGE_UNITS) || (unit == 0 && (imageSrc[3] != '0' || imageSrc[4] != 0))) { RETURN_ERROR1("Invalied TEX# source index"); } *texUnit = unit; if (!Parse_String(parseState, ",")) RETURN_ERROR1("Expected ,"); if (Parse_String(parseState, "1D")) { *texTargetBit = TEXTURE_1D_BIT; } else if (Parse_String(parseState, "2D")) { *texTargetBit = TEXTURE_2D_BIT; } else if (Parse_String(parseState, "3D")) { *texTargetBit = TEXTURE_3D_BIT; } else if (Parse_String(parseState, "CUBE")) { *texTargetBit = TEXTURE_CUBE_BIT; } else if (Parse_String(parseState, "RECT")) { *texTargetBit = TEXTURE_RECT_BIT; } else { RETURN_ERROR1("Invalid texture target token"); } /* update record of referenced texture units */ parseState->texturesUsed[*texUnit] |= *texTargetBit; if (_mesa_bitcount(parseState->texturesUsed[*texUnit]) > 1) { RETURN_ERROR1("Only one texture target can be used per texture unit."); } return GL_TRUE; }
/* * Create a new X/Mesa visual. * Input: display - X11 display * visinfo - an XVisualInfo pointer * rgb_flag - GL_TRUE = RGB mode, * GL_FALSE = color index mode * alpha_flag - alpha buffer requested? * db_flag - GL_TRUE = double-buffered, * GL_FALSE = single buffered * stereo_flag - stereo visual? * ximage_flag - GL_TRUE = use an XImage for back buffer, * GL_FALSE = use an off-screen pixmap for back buffer * depth_size - requested bits/depth values, or zero * stencil_size - requested bits/stencil values, or zero * accum_red_size - requested bits/red accum values, or zero * accum_green_size - requested bits/green accum values, or zero * accum_blue_size - requested bits/blue accum values, or zero * accum_alpha_size - requested bits/alpha accum values, or zero * num_samples - number of samples/pixel if multisampling, or zero * level - visual level, usually 0 * visualCaveat - ala the GLX extension, usually GLX_NONE * Return; a new XMesaVisual or 0 if error. */ PUBLIC XMesaVisual XMesaCreateVisual( Display *display, XVisualInfo * visinfo, GLboolean rgb_flag, GLboolean alpha_flag, GLboolean db_flag, GLboolean stereo_flag, GLboolean ximage_flag, GLint depth_size, GLint stencil_size, GLint accum_red_size, GLint accum_green_size, GLint accum_blue_size, GLint accum_alpha_size, GLint num_samples, GLint level, GLint visualCaveat ) { XMesaDisplay xmdpy = xmesa_init_display(display); XMesaVisual v; GLint red_bits, green_bits, blue_bits, alpha_bits; if (!xmdpy) return NULL; /* For debugging only */ if (_mesa_getenv("MESA_XSYNC")) { /* This makes debugging X easier. * In your debugger, set a breakpoint on _XError to stop when an * X protocol error is generated. */ XSynchronize( display, 1 ); } v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); if (!v) { return NULL; } v->display = display; /* Save a copy of the XVisualInfo struct because the user may Xfree() * the struct but we may need some of the information contained in it * at a later time. */ v->visinfo = (XVisualInfo *) malloc(sizeof(*visinfo)); if (!v->visinfo) { free(v); return NULL; } memcpy(v->visinfo, visinfo, sizeof(*visinfo)); v->ximage_flag = ximage_flag; v->mesa_visual.redMask = visinfo->red_mask; v->mesa_visual.greenMask = visinfo->green_mask; v->mesa_visual.blueMask = visinfo->blue_mask; v->visualID = visinfo->visualid; v->screen = visinfo->screen; #if !(defined(__cplusplus) || defined(c_plusplus)) v->visualType = xmesa_convert_from_x_visual_type(visinfo->class); #else v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); #endif v->mesa_visual.visualRating = visualCaveat; if (alpha_flag) v->mesa_visual.alphaBits = 8; (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 ); { const int xclass = v->visualType; if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { red_bits = _mesa_bitcount(GET_REDMASK(v)); green_bits = _mesa_bitcount(GET_GREENMASK(v)); blue_bits = _mesa_bitcount(GET_BLUEMASK(v)); } else { /* this is an approximation */ int depth; depth = v->visinfo->depth; red_bits = depth / 3; depth -= red_bits; green_bits = depth / 2; depth -= green_bits; blue_bits = depth; alpha_bits = 0; assert( red_bits + green_bits + blue_bits == v->visinfo->depth ); } alpha_bits = v->mesa_visual.alphaBits; } /* initialize visual */ { struct gl_config *vis = &v->mesa_visual; vis->rgbMode = GL_TRUE; vis->doubleBufferMode = db_flag; vis->stereoMode = stereo_flag; vis->redBits = red_bits; vis->greenBits = green_bits; vis->blueBits = blue_bits; vis->alphaBits = alpha_bits; vis->rgbBits = red_bits + green_bits + blue_bits; vis->indexBits = 0; vis->depthBits = depth_size; vis->stencilBits = stencil_size; vis->accumRedBits = accum_red_size; vis->accumGreenBits = accum_green_size; vis->accumBlueBits = accum_blue_size; vis->accumAlphaBits = accum_alpha_size; vis->haveAccumBuffer = accum_red_size > 0; vis->haveDepthBuffer = depth_size > 0; vis->haveStencilBuffer = stencil_size > 0; vis->numAuxBuffers = 0; vis->level = 0; vis->sampleBuffers = 0; vis->samples = 0; } v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; if (db_flag) v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; if (stereo_flag) { v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; if (db_flag) v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; } v->stvis.color_format = choose_pixel_format(v); if (v->stvis.color_format == PIPE_FORMAT_NONE) { free(v->visinfo); free(v); return NULL; } v->stvis.depth_stencil_format = choose_depth_stencil_format(xmdpy, depth_size, stencil_size); v->stvis.accum_format = (accum_red_size + accum_green_size + accum_blue_size + accum_alpha_size) ? PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; v->stvis.samples = num_samples; v->stvis.render_buffer = ST_ATTACHMENT_INVALID; /* XXX minor hack */ v->mesa_visual.level = level; return v; }
/** * Simple case: Blit color, depth or stencil with no scaling or flipping. * XXX we could easily support vertical flipping here. */ static void simple_blit(struct gl_context *ctx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield buffer) { struct gl_renderbuffer *readRb, *drawRb; const GLint width = srcX1 - srcX0; const GLint height = srcY1 - srcY0; GLint row, srcY, dstY, yStep; GLint comps, bytesPerRow; void *rowBuffer; /* only one buffer */ ASSERT(_mesa_bitcount(buffer) == 1); /* no flipping checks */ ASSERT(srcX0 < srcX1); ASSERT(srcY0 < srcY1); ASSERT(dstX0 < dstX1); ASSERT(dstY0 < dstY1); /* size checks */ ASSERT(srcX1 - srcX0 == dstX1 - dstX0); ASSERT(srcY1 - srcY0 == dstY1 - dstY0); /* determine if copy should be bottom-to-top or top-to-bottom */ if (srcY0 > dstY0) { /* src above dst: copy bottom-to-top */ yStep = 1; srcY = srcY0; dstY = dstY0; } else { /* src below dst: copy top-to-bottom */ yStep = -1; srcY = srcY1 - 1; dstY = dstY1 - 1; } switch (buffer) { case GL_COLOR_BUFFER_BIT: readRb = ctx->ReadBuffer->_ColorReadBuffer; drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0]; comps = 4; break; case GL_DEPTH_BUFFER_BIT: readRb = ctx->ReadBuffer->_DepthBuffer; drawRb = ctx->DrawBuffer->_DepthBuffer; comps = 1; break; case GL_STENCIL_BUFFER_BIT: readRb = ctx->ReadBuffer->_StencilBuffer; drawRb = ctx->DrawBuffer->_StencilBuffer; comps = 1; break; default: _mesa_problem(ctx, "unexpected buffer in simple_blit()"); return; } ASSERT(readRb->DataType == drawRb->DataType); /* compute bytes per row */ switch (readRb->DataType) { case GL_UNSIGNED_BYTE: bytesPerRow = comps * width * sizeof(GLubyte); break; case GL_UNSIGNED_SHORT: bytesPerRow = comps * width * sizeof(GLushort); break; case GL_UNSIGNED_INT: bytesPerRow = comps * width * sizeof(GLuint); break; case GL_FLOAT: bytesPerRow = comps * width * sizeof(GLfloat); break; default: _mesa_problem(ctx, "unexpected buffer type in simple_blit"); return; } /* allocate the row buffer */ rowBuffer = malloc(bytesPerRow); if (!rowBuffer) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); return; } for (row = 0; row < height; row++) { readRb->GetRow(ctx, readRb, width, srcX0, srcY, rowBuffer); drawRb->PutRow(ctx, drawRb, width, dstX0, dstY, rowBuffer, NULL); srcY += yStep; dstY += yStep; } free(rowBuffer); }
/** * Recompute the value of swrast->_RasterMask, etc. according to * the current context. The _RasterMask field can be easily tested by * drivers to determine certain basic GL state (does the primitive need * stenciling, logic-op, fog, etc?). */ static void _swrast_update_rasterflags( GLcontext *ctx ) { GLuint rasterMask = 0; if (ctx->Color.AlphaEnabled) rasterMask |= ALPHATEST_BIT; if (ctx->Color.BlendEnabled) rasterMask |= BLEND_BIT; if (ctx->Depth.Test) rasterMask |= DEPTH_BIT; if (ctx->Fog.Enabled) rasterMask |= FOG_BIT; if (ctx->Scissor.Enabled) rasterMask |= CLIP_BIT; if (ctx->Stencil.Enabled) rasterMask |= STENCIL_BIT; if (ctx->Visual.rgbMode) { const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); if (colorMask != 0xffffffff) rasterMask |= MASKING_BIT; if (ctx->Color._LogicOpEnabled) rasterMask |= LOGIC_OP_BIT; if (ctx->Texture._EnabledUnits) rasterMask |= TEXTURE_BIT; } else { if (ctx->Color.IndexMask != 0xffffffff) rasterMask |= MASKING_BIT; if (ctx->Color.IndexLogicOpEnabled) rasterMask |= LOGIC_OP_BIT; } if (ctx->DrawBuffer->UseSoftwareAlphaBuffers && ctx->Color.ColorMask[ACOMP] && ctx->Color.DrawBuffer != GL_NONE) rasterMask |= ALPHABUF_BIT; if ( ctx->Viewport.X < 0 || ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width || ctx->Viewport.Y < 0 || ctx->Viewport.Y + ctx->Viewport.Height > (GLint) ctx->DrawBuffer->Height) { rasterMask |= CLIP_BIT; } if (ctx->Depth.OcclusionTest || ctx->Occlusion.Active) rasterMask |= OCCLUSION_BIT; /* If we're not drawing to exactly one color buffer set the * MULTI_DRAW_BIT flag. Also set it if we're drawing to no * buffers or the RGBA or CI mask disables all writes. */ if (_mesa_bitcount(ctx->Color._DrawDestMask[0]) != 1) { /* more than one color buffer designated for writing (or zero buffers) */ rasterMask |= MULTI_DRAW_BIT; } else if (ctx->Visual.rgbMode && *((GLuint *) ctx->Color.ColorMask) == 0) { rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */ } else if (!ctx->Visual.rgbMode && ctx->Color.IndexMask==0) { rasterMask |= MULTI_DRAW_BIT; /* all color index bits disabled */ } if (ctx->FragmentProgram._Enabled) { rasterMask |= FRAGPROG_BIT; } if (ctx->ATIFragmentShader._Enabled) { rasterMask |= ATIFRAGSHADER_BIT; } SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask; }
/** * Called by glDrawBuffersARB; specifies the destination color renderbuffers * for N fragment program color outputs. * \sa _mesa_DrawBuffer * \param n number of outputs * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the * names cannot specify more than one buffer. For example, * GL_FRONT_AND_BACK is illegal. */ void GLAPIENTRY _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) { GLint output; GLbitfield usedBufferMask, supportedMask; GLbitfield destMask[MAX_DRAW_BUFFERS]; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* Turns out n==0 is a valid input that should not produce an error. * The remaining code below correctly handles the n==0 case. */ if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); return; } supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer); usedBufferMask = 0x0; /* complicated error checking... */ for (output = 0; output < n; output++) { if (buffers[output] == GL_NONE) { destMask[output] = 0x0; } else { destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]); if (destMask[output] == BAD_MASK || _mesa_bitcount(destMask[output]) > 1) { _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); return; } destMask[output] &= supportedMask; if (destMask[output] == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(unsupported buffer)"); return; } if (destMask[output] & usedBufferMask) { /* can't specify a dest buffer more than once! */ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(duplicated buffer)"); return; } /* update bitmask */ usedBufferMask |= destMask[output]; } } /* OK, if we get here, there were no errors so set the new state */ _mesa_drawbuffers(ctx, n, buffers, destMask); /* * Call device driver function. Note that n can be equal to 0, * in which case we don't want to reference buffers[0], which * may not be valid. */ if (ctx->Driver.DrawBuffers) ctx->Driver.DrawBuffers(ctx, n, buffers); else if (ctx->Driver.DrawBuffer) ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE); }
/** * Helper function to set the GL_DRAW_BUFFER state in the context and * current FBO. Called via glDrawBuffer(), glDrawBuffersARB() * * All error checking will have been done prior to calling this function * so nothing should go wrong at this point. * * \param ctx current context * \param n number of color outputs to set * \param buffers array[n] of colorbuffer names, like GL_LEFT. * \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the * colorbuffer names. (i.e. GL_FRONT_AND_BACK => * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). */ void _mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers, const GLbitfield *destMask) { struct gl_framebuffer *fb = ctx->DrawBuffer; GLbitfield mask[MAX_DRAW_BUFFERS]; GLboolean newState = GL_FALSE; if (!destMask) { /* compute destMask values now */ const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb); GLuint output; for (output = 0; output < n; output++) { mask[output] = draw_buffer_enum_to_bitmask(buffers[output]); ASSERT(mask[output] != BAD_MASK); mask[output] &= supportedMask; } destMask = mask; } /* * If n==1, destMask[0] may have up to four bits set. * Otherwise, destMask[x] can only have one bit set. */ if (n == 1) { GLuint count = 0, destMask0 = destMask[0]; while (destMask0) { GLint bufIndex = _mesa_ffs(destMask0) - 1; if (fb->_ColorDrawBufferIndexes[count] != bufIndex) { fb->_ColorDrawBufferIndexes[count] = bufIndex; newState = GL_TRUE; } count++; destMask0 &= ~(1 << bufIndex); } fb->ColorDrawBuffer[0] = buffers[0]; if (fb->_NumColorDrawBuffers != count) { fb->_NumColorDrawBuffers = count; newState = GL_TRUE; } } else { GLuint buf, count = 0; for (buf = 0; buf < n; buf++ ) { if (destMask[buf]) { GLint bufIndex = _mesa_ffs(destMask[buf]) - 1; /* only one bit should be set in the destMask[buf] field */ ASSERT(_mesa_bitcount(destMask[buf]) == 1); if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) { fb->_ColorDrawBufferIndexes[buf] = bufIndex; newState = GL_TRUE; } fb->ColorDrawBuffer[buf] = buffers[buf]; count = buf + 1; } else { if (fb->_ColorDrawBufferIndexes[buf] != -1) { fb->_ColorDrawBufferIndexes[buf] = -1; newState = GL_TRUE; } } } /* set remaining outputs to -1 (GL_NONE) */ while (buf < ctx->Const.MaxDrawBuffers) { if (fb->_ColorDrawBufferIndexes[buf] != -1) { fb->_ColorDrawBufferIndexes[buf] = -1; newState = GL_TRUE; } fb->ColorDrawBuffer[buf] = GL_NONE; buf++; } fb->_NumColorDrawBuffers = count; } if (fb->Name == 0) { /* also set context drawbuffer state */ GLuint buf; for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) { ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf]; newState = GL_TRUE; } } } if (newState) FLUSH_VERTICES(ctx, _NEW_BUFFERS); }
/** * Partition the CURBE between the various users of constant values. * * If the users all fit within the previous allocatation, we avoid changing * the layout because that means reuploading all unit state and uploading new * constant buffers. */ static void calculate_curbe_offsets( struct brw_context *brw ) { struct gl_context *ctx = &brw->ctx; /* BRW_NEW_FS_PROG_DATA */ const GLuint nr_fp_regs = (brw->wm.base.prog_data->nr_params + 15) / 16; /* BRW_NEW_VS_PROG_DATA */ const GLuint nr_vp_regs = (brw->vs.base.prog_data->nr_params + 15) / 16; GLuint nr_clip_regs = 0; GLuint total_regs; /* _NEW_TRANSFORM */ if (ctx->Transform.ClipPlanesEnabled) { GLuint nr_planes = 6 + _mesa_bitcount(ctx->Transform.ClipPlanesEnabled); nr_clip_regs = (nr_planes * 4 + 15) / 16; } total_regs = nr_fp_regs + nr_vp_regs + nr_clip_regs; /* The CURBE allocation size is limited to 32 512-bit units (128 EU * registers, or 1024 floats). See CS_URB_STATE in the gen4 or gen5 * (volume 1, part 1) PRMs. * * Note that in brw_fs.cpp we're only loading up to 16 EU registers of * values as push constants before spilling to pull constants, and in * brw_vec4.cpp we're loading up to 32 registers of push constants. An EU * register is 1/2 of one of these URB entry units, so that leaves us 16 EU * regs for clip. */ assert(total_regs <= 32); /* Lazy resize: */ if (nr_fp_regs > brw->curbe.wm_size || nr_vp_regs > brw->curbe.vs_size || nr_clip_regs != brw->curbe.clip_size || (total_regs < brw->curbe.total_size / 4 && brw->curbe.total_size > 16)) { GLuint reg = 0; /* Calculate a new layout: */ reg = 0; brw->curbe.wm_start = reg; brw->curbe.wm_size = nr_fp_regs; reg += nr_fp_regs; brw->curbe.clip_start = reg; brw->curbe.clip_size = nr_clip_regs; reg += nr_clip_regs; brw->curbe.vs_start = reg; brw->curbe.vs_size = nr_vp_regs; reg += nr_vp_regs; brw->curbe.total_size = reg; if (0) fprintf(stderr, "curbe wm %d+%d clip %d+%d vs %d+%d\n", brw->curbe.wm_start, brw->curbe.wm_size, brw->curbe.clip_start, brw->curbe.clip_size, brw->curbe.vs_start, brw->curbe.vs_size ); brw->ctx.NewDriverState |= BRW_NEW_CURBE_OFFSETS; } }
/** * \note This routine refers to derived texture matrix values to * compute the ENABLE_TEXMAT flags, but is only called on * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT * flags are updated by _mesa_update_texture_matrices, above. * * \param ctx GL context. */ static void update_texture_state( struct gl_context *ctx ) { GLuint unit; struct gl_program *fprog = NULL; struct gl_program *vprog = NULL; GLbitfield enabledFragUnits = 0x0; if (ctx->Shader.CurrentVertexProgram && ctx->Shader.CurrentVertexProgram->LinkStatus) { vprog = ctx->Shader.CurrentVertexProgram->_LinkedShaders[MESA_SHADER_VERTEX]->Program; } else if (ctx->VertexProgram._Enabled) { /* XXX enable this if/when non-shader vertex programs get * texture fetches: vprog = &ctx->VertexProgram.Current->Base; */ } if (ctx->Shader.CurrentFragmentProgram && ctx->Shader.CurrentFragmentProgram->LinkStatus) { fprog = ctx->Shader.CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program; } else if (ctx->FragmentProgram._Enabled) { fprog = &ctx->FragmentProgram.Current->Base; } /* FINISHME: Geometry shader texture accesses should also be considered * FINISHME: here. */ /* TODO: only set this if there are actual changes */ ctx->NewState |= _NEW_TEXTURE; ctx->Texture._EnabledUnits = 0x0; ctx->Texture._GenFlags = 0x0; ctx->Texture._TexMatEnabled = 0x0; ctx->Texture._TexGenEnabled = 0x0; /* * Update texture unit state. */ for (unit = 0; unit < ctx->Const.MaxCombinedTextureImageUnits; unit++) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; GLbitfield enabledVertTargets = 0x0; GLbitfield enabledFragTargets = 0x0; GLbitfield enabledTargets = 0x0; GLuint texIndex; /* Get the bitmask of texture target enables. * enableBits will be a mask of the TEXTURE_*_BIT flags indicating * which texture targets are enabled (fixed function) or referenced * by a fragment program/program. When multiple flags are set, we'll * settle on the one with highest priority (see below). */ if (vprog) { enabledVertTargets |= vprog->TexturesUsed[unit]; } if (fprog) { enabledFragTargets |= fprog->TexturesUsed[unit]; } else { /* fixed-function fragment program */ enabledFragTargets |= texUnit->Enabled; } enabledTargets = enabledVertTargets | enabledFragTargets; texUnit->_ReallyEnabled = 0x0; if (enabledTargets == 0x0) { /* neither vertex nor fragment processing uses this unit */ continue; } /* Look for the highest priority texture target that's enabled (or used * by the vert/frag shaders) and "complete". That's the one we'll use * for texturing. If we're using vert/frag program we're guaranteed * that bitcount(enabledBits) <= 1. * Note that the TEXTURE_x_INDEX values are in high to low priority. */ for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) { if (enabledTargets & (1 << texIndex)) { struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex]; struct gl_sampler_object *sampler = texUnit->Sampler ? texUnit->Sampler : &texObj->Sampler; if (!_mesa_is_texture_complete(texObj, sampler)) { _mesa_test_texobj_completeness(ctx, texObj); } if (_mesa_is_texture_complete(texObj, sampler)) { texUnit->_ReallyEnabled = 1 << texIndex; _mesa_reference_texobj(&texUnit->_Current, texObj); break; } } } if (!texUnit->_ReallyEnabled) { if (fprog) { /* If we get here it means the shader is expecting a texture * object, but there isn't one (or it's incomplete). Use the * fallback texture. */ struct gl_texture_object *texObj; gl_texture_index texTarget; assert(_mesa_bitcount(enabledTargets) == 1); texTarget = (gl_texture_index) (ffs(enabledTargets) - 1); texObj = _mesa_get_fallback_texture(ctx, texTarget); _mesa_reference_texobj(&texUnit->_Current, texObj); texUnit->_ReallyEnabled = 1 << texTarget; } else { /* fixed-function: texture unit is really disabled */ continue; } } /* if we get here, we know this texture unit is enabled */ ctx->Texture._EnabledUnits |= (1 << unit); if (enabledFragTargets) enabledFragUnits |= (1 << unit); update_tex_combine(ctx, texUnit); } /* Determine which texture coordinate sets are actually needed */ if (fprog) { const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1; ctx->Texture._EnabledCoordUnits = (fprog->InputsRead >> FRAG_ATTRIB_TEX0) & coordMask; } else {
void GLAPIENTRY _mesa_ColorTable( GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data ) { static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 }; static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 }; GET_CURRENT_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; struct gl_texture_object *texObj = NULL; struct gl_color_table *table = NULL; GLboolean proxy = GL_FALSE; GLint baseFormat; const GLfloat *scale = one, *bias = zero; GLint comps; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */ switch (target) { case GL_TEXTURE_1D: texObj = texUnit->Current1D; table = &texObj->Palette; break; case GL_TEXTURE_2D: texObj = texUnit->Current2D; table = &texObj->Palette; break; case GL_TEXTURE_3D: texObj = texUnit->Current3D; table = &texObj->Palette; break; case GL_TEXTURE_CUBE_MAP_ARB: if (!ctx->Extensions.ARB_texture_cube_map) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } texObj = texUnit->CurrentCubeMap; table = &texObj->Palette; break; case GL_PROXY_TEXTURE_1D: texObj = ctx->Texture.Proxy1D; table = &texObj->Palette; proxy = GL_TRUE; break; case GL_PROXY_TEXTURE_2D: texObj = ctx->Texture.Proxy2D; table = &texObj->Palette; proxy = GL_TRUE; break; case GL_PROXY_TEXTURE_3D: texObj = ctx->Texture.Proxy3D; table = &texObj->Palette; proxy = GL_TRUE; break; case GL_PROXY_TEXTURE_CUBE_MAP_ARB: if (!ctx->Extensions.ARB_texture_cube_map) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } texObj = ctx->Texture.ProxyCubeMap; table = &texObj->Palette; break; case GL_SHARED_TEXTURE_PALETTE_EXT: table = &ctx->Texture.Palette; break; case GL_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION]; scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION]; bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION]; break; case GL_PROXY_COLOR_TABLE: table = &ctx->ProxyColorTable[COLORTABLE_PRECONVOLUTION]; proxy = GL_TRUE; break; case GL_TEXTURE_COLOR_TABLE_SGI: if (!ctx->Extensions.SGI_texture_color_table) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } table = &(texUnit->ColorTable); scale = ctx->Pixel.TextureColorTableScale; bias = ctx->Pixel.TextureColorTableBias; break; case GL_PROXY_TEXTURE_COLOR_TABLE_SGI: if (!ctx->Extensions.SGI_texture_color_table) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } table = &(texUnit->ProxyColorTable); proxy = GL_TRUE; break; case GL_POST_CONVOLUTION_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION]; scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION]; bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION]; break; case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE: table = &ctx->ProxyColorTable[COLORTABLE_POSTCONVOLUTION]; proxy = GL_TRUE; break; case GL_POST_COLOR_MATRIX_COLOR_TABLE: table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX]; scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX]; bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX]; break; case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE: table = &ctx->ProxyColorTable[COLORTABLE_POSTCOLORMATRIX]; proxy = GL_TRUE; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } assert(table); if (!_mesa_is_legal_format_and_type(ctx, format, type) || format == GL_INTENSITY) { _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTable(format or type)"); return; } baseFormat = base_colortab_format(internalFormat); if (baseFormat < 0) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(internalFormat)"); return; } if (width < 0 || (width != 0 && _mesa_bitcount(width) != 1)) { /* error */ if (proxy) { table->Size = 0; table->InternalFormat = (GLenum) 0; table->_BaseFormat = (GLenum) 0; } else { _mesa_error(ctx, GL_INVALID_VALUE, "glColorTable(width=%d)", width); } return; } if (width > (GLsizei) ctx->Const.MaxColorTableSize) { if (proxy) { table->Size = 0; table->InternalFormat = (GLenum) 0; table->_BaseFormat = (GLenum) 0; } else { _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glColorTable(width)"); } return; } table->Size = width; table->InternalFormat = internalFormat; table->_BaseFormat = (GLenum) baseFormat; comps = _mesa_components_in_format(table->_BaseFormat); assert(comps > 0); /* error should have been caught sooner */ if (!proxy) { _mesa_free_colortable_data(table); if (width > 0) { table->TableF = (GLfloat *) _mesa_malloc(comps * width * sizeof(GLfloat)); table->TableUB = (GLubyte *) _mesa_malloc(comps * width * sizeof(GLubyte)); if (!table->TableF || !table->TableUB) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glColorTable"); return; } store_colortable_entries(ctx, table, 0, width, /* start, count */ format, type, data, scale[0], bias[0], scale[1], bias[1], scale[2], bias[2], scale[3], bias[3]); } } /* proxy */ /* do this after the table's Type and Format are set */ set_component_sizes(table); if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) { /* texture object palette, texObj==NULL means the shared palette */ if (ctx->Driver.UpdateTexturePalette) { (*ctx->Driver.UpdateTexturePalette)( ctx, texObj ); } } ctx->NewState |= _NEW_PIXEL; }
/* * Create a new X/Mesa visual. * Input: display - X11 display * visinfo - an XVisualInfo pointer * rgb_flag - GL_TRUE = RGB mode, * GL_FALSE = color index mode * alpha_flag - alpha buffer requested? * db_flag - GL_TRUE = double-buffered, * GL_FALSE = single buffered * stereo_flag - stereo visual? * ximage_flag - GL_TRUE = use an XImage for back buffer, * GL_FALSE = use an off-screen pixmap for back buffer * depth_size - requested bits/depth values, or zero * stencil_size - requested bits/stencil values, or zero * accum_red_size - requested bits/red accum values, or zero * accum_green_size - requested bits/green accum values, or zero * accum_blue_size - requested bits/blue accum values, or zero * accum_alpha_size - requested bits/alpha accum values, or zero * num_samples - number of samples/pixel if multisampling, or zero * level - visual level, usually 0 * visualCaveat - ala the GLX extension, usually GLX_NONE * Return; a new XMesaVisual or 0 if error. */ PUBLIC XMesaVisual XMesaCreateVisual( XMesaDisplay *display, XMesaVisualInfo visinfo, GLboolean rgb_flag, GLboolean alpha_flag, GLboolean db_flag, GLboolean stereo_flag, GLboolean ximage_flag, GLint depth_size, GLint stencil_size, GLint accum_red_size, GLint accum_green_size, GLint accum_blue_size, GLint accum_alpha_size, GLint num_samples, GLint level, GLint visualCaveat ) { char *gamma; XMesaVisual v; GLint red_bits, green_bits, blue_bits, alpha_bits; /* For debugging only */ if (_mesa_getenv("MESA_XSYNC")) { /* This makes debugging X easier. * In your debugger, set a breakpoint on _XError to stop when an * X protocol error is generated. */ XSynchronize( display, 1 ); } /* Color-index rendering not supported. */ if (!rgb_flag) return NULL; v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); if (!v) { return NULL; } v->display = display; /* Save a copy of the XVisualInfo struct because the user may Xfree() * the struct but we may need some of the information contained in it * at a later time. */ v->visinfo = (XVisualInfo *) malloc(sizeof(*visinfo)); if(!v->visinfo) { free(v); return NULL; } memcpy(v->visinfo, visinfo, sizeof(*visinfo)); /* check for MESA_GAMMA environment variable */ gamma = _mesa_getenv("MESA_GAMMA"); if (gamma) { v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0; sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma ); if (v->RedGamma<=0.0) v->RedGamma = 1.0; if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma; if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma; } else { v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0; } v->ximage_flag = ximage_flag; v->mesa_visual.redMask = visinfo->red_mask; v->mesa_visual.greenMask = visinfo->green_mask; v->mesa_visual.blueMask = visinfo->blue_mask; v->visualID = visinfo->visualid; v->screen = visinfo->screen; #if !(defined(__cplusplus) || defined(c_plusplus)) v->visualType = xmesa_convert_from_x_visual_type(visinfo->class); #else v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); #endif v->mesa_visual.visualRating = visualCaveat; if (alpha_flag) v->mesa_visual.alphaBits = 8; (void) initialize_visual_and_buffer( v, NULL, 0, 0 ); { const int xclass = v->visualType; if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { red_bits = _mesa_bitcount(GET_REDMASK(v)); green_bits = _mesa_bitcount(GET_GREENMASK(v)); blue_bits = _mesa_bitcount(GET_BLUEMASK(v)); } else { /* this is an approximation */ int depth; depth = GET_VISUAL_DEPTH(v); red_bits = depth / 3; depth -= red_bits; green_bits = depth / 2; depth -= green_bits; blue_bits = depth; alpha_bits = 0; assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); } alpha_bits = v->mesa_visual.alphaBits; } if (!_mesa_initialize_visual(&v->mesa_visual, db_flag, stereo_flag, red_bits, green_bits, blue_bits, alpha_bits, depth_size, stencil_size, accum_red_size, accum_green_size, accum_blue_size, accum_alpha_size, 0)) { FREE(v); return NULL; } /* XXX minor hack */ v->mesa_visual.level = level; return v; }
/** * Setup RGB rendering for a window with a True/DirectColor visual. */ static void setup_truecolor(XMesaVisual v, XMesaBuffer buffer, XMesaColormap cmap) { unsigned long rmask, gmask, bmask; (void) buffer; (void) cmap; /* Compute red multiplier (mask) and bit shift */ v->rshift = 0; rmask = GET_REDMASK(v); while ((rmask & 1)==0) { v->rshift++; rmask = rmask >> 1; } /* Compute green multiplier (mask) and bit shift */ v->gshift = 0; gmask = GET_GREENMASK(v); while ((gmask & 1)==0) { v->gshift++; gmask = gmask >> 1; } /* Compute blue multiplier (mask) and bit shift */ v->bshift = 0; bmask = GET_BLUEMASK(v); while ((bmask & 1)==0) { v->bshift++; bmask = bmask >> 1; } /* * Compute component-to-pixel lookup tables and dithering kernel */ { static GLubyte kernel[16] = { 0*16, 8*16, 2*16, 10*16, 12*16, 4*16, 14*16, 6*16, 3*16, 11*16, 1*16, 9*16, 15*16, 7*16, 13*16, 5*16, }; GLint rBits = _mesa_bitcount(rmask); GLint gBits = _mesa_bitcount(gmask); GLint bBits = _mesa_bitcount(bmask); GLint maxBits; GLuint i; /* convert pixel components in [0,_mask] to RGB values in [0,255] */ for (i=0; i<=rmask; i++) v->PixelToR[i] = (unsigned char) ((i * 255) / rmask); for (i=0; i<=gmask; i++) v->PixelToG[i] = (unsigned char) ((i * 255) / gmask); for (i=0; i<=bmask; i++) v->PixelToB[i] = (unsigned char) ((i * 255) / bmask); /* convert RGB values from [0,255] to pixel components */ for (i=0;i<256;i++) { GLint r = gamma_adjust(v->RedGamma, i, 255); GLint g = gamma_adjust(v->GreenGamma, i, 255); GLint b = gamma_adjust(v->BlueGamma, i, 255); v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift; v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift; v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift; } /* overflow protection */ for (i=256;i<512;i++) { v->RtoPixel[i] = v->RtoPixel[255]; v->GtoPixel[i] = v->GtoPixel[255]; v->BtoPixel[i] = v->BtoPixel[255]; } /* setup dithering kernel */ maxBits = rBits; if (gBits > maxBits) maxBits = gBits; if (bBits > maxBits) maxBits = bBits; for (i=0;i<16;i++) { v->Kernel[i] = kernel[i] >> maxBits; } v->undithered_pf = PF_Truecolor; v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor; } /* * Now check for TrueColor visuals which we can optimize. */ if ( GET_REDMASK(v) ==0x0000ff && GET_GREENMASK(v)==0x00ff00 && GET_BLUEMASK(v) ==0xff0000 && CHECK_BYTE_ORDER(v) && v->BitsPerPixel==32 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { /* common 32 bpp config used on SGI, Sun */ v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; /* ABGR */ } else if (GET_REDMASK(v) == 0xff0000 && GET_GREENMASK(v)== 0x00ff00 && GET_BLUEMASK(v) == 0x0000ff && CHECK_BYTE_ORDER(v) && v->RedGamma == 1.0 && v->GreenGamma == 1.0 && v->BlueGamma == 1.0){ if (v->BitsPerPixel==32) { /* if 32 bpp, and visual indicates 8 bpp alpha channel */ if (GET_VISUAL_DEPTH(v) == 32 && v->mesa_visual.alphaBits == 8) v->undithered_pf = v->dithered_pf = PF_8A8R8G8B; /* ARGB */ else v->undithered_pf = v->dithered_pf = PF_8R8G8B; /* xRGB */ } else if (v->BitsPerPixel == 24) { v->undithered_pf = v->dithered_pf = PF_8R8G8B24; /* RGB */ } } else if (GET_REDMASK(v) ==0xf800 && GET_GREENMASK(v)==0x07e0 && GET_BLUEMASK(v) ==0x001f && CHECK_BYTE_ORDER(v) && v->BitsPerPixel==16 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { /* 5-6-5 RGB */ v->undithered_pf = PF_5R6G5B; v->dithered_pf = PF_Dither_5R6G5B; } }
void GLAPIENTRY _mesa_ColorTable( GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data ) { GET_CURRENT_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; struct gl_texture_object *texObj = NULL; struct gl_color_table *table = NULL; GLboolean proxy = GL_FALSE; GLint baseFormat; GLfloat rScale = 1.0, gScale = 1.0, bScale = 1.0, aScale = 1.0; GLfloat rBias = 0.0, gBias = 0.0, bBias = 0.0, aBias = 0.0; GLenum tableType = CHAN_TYPE; GLint comps; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */ switch (target) { case GL_TEXTURE_1D: texObj = texUnit->Current1D; table = &texObj->Palette; break; case GL_TEXTURE_2D: texObj = texUnit->Current2D; table = &texObj->Palette; break; case GL_TEXTURE_3D: texObj = texUnit->Current3D; table = &texObj->Palette; break; case GL_TEXTURE_CUBE_MAP_ARB: if (!ctx->Extensions.ARB_texture_cube_map) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } texObj = texUnit->CurrentCubeMap; table = &texObj->Palette; break; case GL_PROXY_TEXTURE_1D: texObj = ctx->Texture.Proxy1D; table = &texObj->Palette; proxy = GL_TRUE; break; case GL_PROXY_TEXTURE_2D: texObj = ctx->Texture.Proxy2D; table = &texObj->Palette; proxy = GL_TRUE; break; case GL_PROXY_TEXTURE_3D: texObj = ctx->Texture.Proxy3D; table = &texObj->Palette; proxy = GL_TRUE; break; case GL_PROXY_TEXTURE_CUBE_MAP_ARB: if (!ctx->Extensions.ARB_texture_cube_map) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } texObj = ctx->Texture.ProxyCubeMap; table = &texObj->Palette; break; case GL_SHARED_TEXTURE_PALETTE_EXT: table = &ctx->Texture.Palette; break; case GL_COLOR_TABLE: table = &ctx->ColorTable; tableType = GL_FLOAT; rScale = ctx->Pixel.ColorTableScale[0]; gScale = ctx->Pixel.ColorTableScale[1]; bScale = ctx->Pixel.ColorTableScale[2]; aScale = ctx->Pixel.ColorTableScale[3]; rBias = ctx->Pixel.ColorTableBias[0]; gBias = ctx->Pixel.ColorTableBias[1]; bBias = ctx->Pixel.ColorTableBias[2]; aBias = ctx->Pixel.ColorTableBias[3]; break; case GL_PROXY_COLOR_TABLE: table = &ctx->ProxyColorTable; proxy = GL_TRUE; break; case GL_TEXTURE_COLOR_TABLE_SGI: if (!ctx->Extensions.SGI_texture_color_table) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } table = &(texUnit->ColorTable); tableType = GL_FLOAT; rScale = ctx->Pixel.TextureColorTableScale[0]; gScale = ctx->Pixel.TextureColorTableScale[1]; bScale = ctx->Pixel.TextureColorTableScale[2]; aScale = ctx->Pixel.TextureColorTableScale[3]; rBias = ctx->Pixel.TextureColorTableBias[0]; gBias = ctx->Pixel.TextureColorTableBias[1]; bBias = ctx->Pixel.TextureColorTableBias[2]; aBias = ctx->Pixel.TextureColorTableBias[3]; break; case GL_PROXY_TEXTURE_COLOR_TABLE_SGI: if (!ctx->Extensions.SGI_texture_color_table) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } table = &(texUnit->ProxyColorTable); proxy = GL_TRUE; break; case GL_POST_CONVOLUTION_COLOR_TABLE: table = &ctx->PostConvolutionColorTable; tableType = GL_FLOAT; rScale = ctx->Pixel.PCCTscale[0]; gScale = ctx->Pixel.PCCTscale[1]; bScale = ctx->Pixel.PCCTscale[2]; aScale = ctx->Pixel.PCCTscale[3]; rBias = ctx->Pixel.PCCTbias[0]; gBias = ctx->Pixel.PCCTbias[1]; bBias = ctx->Pixel.PCCTbias[2]; aBias = ctx->Pixel.PCCTbias[3]; break; case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE: table = &ctx->ProxyPostConvolutionColorTable; proxy = GL_TRUE; break; case GL_POST_COLOR_MATRIX_COLOR_TABLE: table = &ctx->PostColorMatrixColorTable; tableType = GL_FLOAT; rScale = ctx->Pixel.PCMCTscale[0]; gScale = ctx->Pixel.PCMCTscale[1]; bScale = ctx->Pixel.PCMCTscale[2]; aScale = ctx->Pixel.PCMCTscale[3]; rBias = ctx->Pixel.PCMCTbias[0]; gBias = ctx->Pixel.PCMCTbias[1]; bBias = ctx->Pixel.PCMCTbias[2]; aBias = ctx->Pixel.PCMCTbias[3]; break; case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE: table = &ctx->ProxyPostColorMatrixColorTable; proxy = GL_TRUE; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); return; } assert(table); if (!_mesa_is_legal_format_and_type(ctx, format, type) || format == GL_INTENSITY) { _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTable(format or type)"); return; } baseFormat = base_colortab_format(internalFormat); if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(internalFormat)"); return; } if (width < 0 || (width != 0 && _mesa_bitcount(width) != 1)) { /* error */ if (proxy) { table->Size = 0; table->IntFormat = (GLenum) 0; table->Format = (GLenum) 0; } else { _mesa_error(ctx, GL_INVALID_VALUE, "glColorTable(width=%d)", width); } return; } if (width > (GLsizei) ctx->Const.MaxColorTableSize) { if (proxy) { table->Size = 0; table->IntFormat = (GLenum) 0; table->Format = (GLenum) 0; } else { _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glColorTable(width)"); } return; } table->Size = width; table->IntFormat = internalFormat; table->Format = (GLenum) baseFormat; set_component_sizes(table); comps = _mesa_components_in_format(table->Format); assert(comps > 0); /* error should have been caught sooner */ if (!proxy) { /* free old table, if any */ if (table->Table) { FREE(table->Table); table->Table = NULL; } if (width > 0) { if (tableType == GL_FLOAT) { table->Type = GL_FLOAT; table->Table = MALLOC(comps * width * sizeof(GLfloat)); } else { table->Type = CHAN_TYPE; table->Table = MALLOC(comps * width * sizeof(GLchan)); } if (!table->Table) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glColorTable"); return; } store_colortable_entries(ctx, table, 0, width, /* start, count */ format, type, data, rScale, rBias, gScale, gBias, bScale, bBias, aScale, aBias); } } /* proxy */ if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) { /* texture object palette, texObj==NULL means the shared palette */ if (ctx->Driver.UpdateTexturePalette) { (*ctx->Driver.UpdateTexturePalette)( ctx, texObj ); } } ctx->NewState |= _NEW_PIXEL; }
/** * Called by glDrawBuffersARB; specifies the destination color renderbuffers * for N fragment program color outputs. * \sa _mesa_DrawBuffer * \param n number of outputs * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the * names cannot specify more than one buffer. For example, * GL_FRONT_AND_BACK is illegal. */ void GLAPIENTRY _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) { GLint output; GLbitfield usedBufferMask, supportedMask; GLbitfield destMask[MAX_DRAW_BUFFERS]; GET_CURRENT_CONTEXT(ctx); FLUSH_VERTICES(ctx, 0); /* Turns out n==0 is a valid input that should not produce an error. * The remaining code below correctly handles the n==0 case. * * From the OpenGL 3.0 specification, page 258: * "An INVALID_VALUE error is generated if n is greater than * MAX_DRAW_BUFFERS." */ if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); return; } supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer); usedBufferMask = 0x0; /* From the ES 3.0 specification, page 180: * "If the GL is bound to the default framebuffer, then n must be 1 * and the constant must be BACK or NONE." */ if (_mesa_is_gles3(ctx) && _mesa_is_winsys_fbo(ctx->DrawBuffer) && (n != 1 || (buffers[0] != GL_NONE && buffers[0] != GL_BACK))) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)"); return; } /* complicated error checking... */ for (output = 0; output < n; output++) { if (buffers[output] == GL_NONE) { destMask[output] = 0x0; } else { /* Page 259 (page 275 of the PDF) in section 4.2.1 of the OpenGL 3.0 * spec (20080923) says: * * "If the GL is bound to a framebuffer object and DrawBuffers is * supplied with [...] COLOR_ATTACHMENTm where m is greater than * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error * INVALID_OPERATION results." */ if (_mesa_is_user_fbo(ctx->DrawBuffer) && buffers[output] >= GL_COLOR_ATTACHMENT0 + ctx->Const.MaxDrawBuffers) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(buffer)"); return; } destMask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]); /* From the OpenGL 3.0 specification, page 258: * "Each buffer listed in bufs must be one of the values from tables * 4.5 or 4.6. Otherwise, an INVALID_ENUM error is generated. */ if (destMask[output] == BAD_MASK) { _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); return; } /* From the OpenGL 4.0 specification, page 256: * "For both the default framebuffer and framebuffer objects, the * constants FRONT, BACK, LEFT, RIGHT, and FRONT_AND_BACK are not * valid in the bufs array passed to DrawBuffers, and will result in * the error INVALID_ENUM. This restriction is because these * constants may themselves refer to multiple buffers, as shown in * table 4.4." * Previous versions of the OpenGL specification say INVALID_OPERATION, * but the Khronos conformance tests expect INVALID_ENUM. */ if (_mesa_bitcount(destMask[output]) > 1) { _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); return; } /* From the OpenGL 3.0 specification, page 259: * "If the GL is bound to the default framebuffer and DrawBuffers is * supplied with a constant (other than NONE) that does not indicate * any of the color buffers allocated to the GL context by the window * system, the error INVALID_OPERATION will be generated. * * If the GL is bound to a framebuffer object and DrawBuffers is * supplied with a constant from table 4.6 [...] then the error * INVALID_OPERATION results." */ destMask[output] &= supportedMask; if (destMask[output] == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(unsupported buffer)"); return; } /* ES 3.0 is even more restrictive. From the ES 3.0 spec, page 180: * "If the GL is bound to a framebuffer object, the ith buffer listed * in bufs must be COLOR_ATTACHMENTi or NONE. [...] INVALID_OPERATION." */ if (_mesa_is_gles3(ctx) && _mesa_is_user_fbo(ctx->DrawBuffer) && buffers[output] != GL_NONE && buffers[output] != GL_COLOR_ATTACHMENT0 + output) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)"); return; } /* From the OpenGL 3.0 specification, page 258: * "Except for NONE, a buffer may not appear more than once in the * array pointed to by bufs. Specifying a buffer more then once will * result in the error INVALID_OPERATION." */ if (destMask[output] & usedBufferMask) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(duplicated buffer)"); return; } /* update bitmask */ usedBufferMask |= destMask[output]; } } /* OK, if we get here, there were no errors so set the new state */ _mesa_drawbuffers(ctx, n, buffers, destMask); /* * Call device driver function. Note that n can be equal to 0, * in which case we don't want to reference buffers[0], which * may not be valid. */ if (ctx->Driver.DrawBuffers) ctx->Driver.DrawBuffers(ctx, n, buffers); else if (ctx->Driver.DrawBuffer) ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE); }
/** * Helper function to set the GL_DRAW_BUFFER state in the context and * current FBO. Called via glDrawBuffer(), glDrawBuffersARB() * * All error checking will have been done prior to calling this function * so nothing should go wrong at this point. * * \param ctx current context * \param n number of color outputs to set * \param buffers array[n] of colorbuffer names, like GL_LEFT. * \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the * colorbuffer names. (i.e. GL_FRONT_AND_BACK => * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT). */ void _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, const GLbitfield *destMask) { struct gl_framebuffer *fb = ctx->DrawBuffer; GLbitfield mask[MAX_DRAW_BUFFERS]; GLuint buf; if (!destMask) { /* compute destMask values now */ const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb); GLuint output; for (output = 0; output < n; output++) { mask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]); ASSERT(mask[output] != BAD_MASK); mask[output] &= supportedMask; } destMask = mask; } /* * destMask[0] may have up to four bits set * (ex: glDrawBuffer(GL_FRONT_AND_BACK)). * Otherwise, destMask[x] can only have one bit set. */ if (n > 0 && _mesa_bitcount(destMask[0]) > 1) { GLuint count = 0, destMask0 = destMask[0]; while (destMask0) { GLint bufIndex = ffs(destMask0) - 1; if (fb->_ColorDrawBufferIndexes[count] != bufIndex) { updated_drawbuffers(ctx); fb->_ColorDrawBufferIndexes[count] = bufIndex; } count++; destMask0 &= ~(1 << bufIndex); } fb->ColorDrawBuffer[0] = buffers[0]; fb->_NumColorDrawBuffers = count; } else { GLuint count = 0; for (buf = 0; buf < n; buf++ ) { if (destMask[buf]) { GLint bufIndex = ffs(destMask[buf]) - 1; /* only one bit should be set in the destMask[buf] field */ ASSERT(_mesa_bitcount(destMask[buf]) == 1); if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) { updated_drawbuffers(ctx); fb->_ColorDrawBufferIndexes[buf] = bufIndex; } count = buf + 1; } else { if (fb->_ColorDrawBufferIndexes[buf] != -1) { updated_drawbuffers(ctx); fb->_ColorDrawBufferIndexes[buf] = -1; } } fb->ColorDrawBuffer[buf] = buffers[buf]; } fb->_NumColorDrawBuffers = count; } /* set remaining outputs to -1 (GL_NONE) */ for (buf = fb->_NumColorDrawBuffers; buf < ctx->Const.MaxDrawBuffers; buf++) { if (fb->_ColorDrawBufferIndexes[buf] != -1) { updated_drawbuffers(ctx); fb->_ColorDrawBufferIndexes[buf] = -1; } } for (buf = n; buf < ctx->Const.MaxDrawBuffers; buf++) { fb->ColorDrawBuffer[buf] = GL_NONE; } if (_mesa_is_winsys_fbo(fb)) { /* also set context drawbuffer state */ for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) { updated_drawbuffers(ctx); ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf]; } } } }
void _mesa_Histogram(GLenum target, GLsizei width, GLenum internalFormat, GLboolean sink) { GLuint i; GLboolean error = GL_FALSE; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* sideeffects */ if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) { _mesa_error(ctx, GL_INVALID_OPERATION, "glHistogram"); return; } if (target != GL_HISTOGRAM && target != GL_PROXY_HISTOGRAM) { _mesa_error(ctx, GL_INVALID_ENUM, "glHistogram(target)"); return; } if (width < 0 || width > HISTOGRAM_TABLE_SIZE) { if (target == GL_PROXY_HISTOGRAM) { error = GL_TRUE; } else { if (width < 0) _mesa_error(ctx, GL_INVALID_VALUE, "glHistogram(width)"); else _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glHistogram(width)"); return; } } if (width != 0 && _mesa_bitcount(width) != 1) { if (target == GL_PROXY_HISTOGRAM) { error = GL_TRUE; } else { _mesa_error(ctx, GL_INVALID_VALUE, "glHistogram(width)"); return; } } if (base_histogram_format(internalFormat) < 0) { if (target == GL_PROXY_HISTOGRAM) { error = GL_TRUE; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glHistogram(internalFormat)"); return; } } /* reset histograms */ for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) { ctx->Histogram.Count[i][0] = 0; ctx->Histogram.Count[i][1] = 0; ctx->Histogram.Count[i][2] = 0; ctx->Histogram.Count[i][3] = 0; } if (error) { ctx->Histogram.Width = 0; ctx->Histogram.Format = 0; ctx->Histogram.RedSize = 0; ctx->Histogram.GreenSize = 0; ctx->Histogram.BlueSize = 0; ctx->Histogram.AlphaSize = 0; ctx->Histogram.LuminanceSize = 0; } else { ctx->Histogram.Width = width; ctx->Histogram.Format = internalFormat; ctx->Histogram.Sink = sink; ctx->Histogram.RedSize = 8 * sizeof(GLuint); ctx->Histogram.GreenSize = 8 * sizeof(GLuint); ctx->Histogram.BlueSize = 8 * sizeof(GLuint); ctx->Histogram.AlphaSize = 8 * sizeof(GLuint); ctx->Histogram.LuminanceSize = 8 * sizeof(GLuint); } ctx->NewState |= _NEW_PIXEL; }