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);
}
Exemple #2
0
/**
 * 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;
}
Exemple #3
0
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;
}
Exemple #5
0
/*
 * 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;
}
Exemple #6
0
/**
 * 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;
}
Exemple #8
0
/**
 * 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);
}
Exemple #9
0
/**
 * 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);
}
Exemple #10
0
/**
 * 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;
   }
}
Exemple #11
0
/**
 * \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 {
Exemple #12
0
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;
}
Exemple #13
0
/*
 * 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;
}
Exemple #14
0
/**
 * 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;
}
Exemple #16
0
/**
 * 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);
}
Exemple #17
0
/**
 * 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];
         }
      }
   }
}
Exemple #18
0
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;
}