Exemplo n.º 1
0
PUBLIC void
glXUseXFont(Font font, int first, int count, int listbase)
{
   Display *dpy;
   Window win;
   Pixmap pixmap;
   GC gc;
   XGCValues values;
   unsigned long valuemask;
   XFontStruct *fs;
   GLint swapbytes, lsbfirst, rowlength;
   GLint skiprows, skippixels, alignment;
   unsigned int max_width, max_height, max_bm_width, max_bm_height;
   GLubyte *bm;
   int i;

   dpy = glXGetCurrentDisplay();
   if (!dpy)
      return;			/* I guess glXMakeCurrent wasn't called */
   i = DefaultScreen(dpy);
   win = RootWindow(dpy, i);

   fs = XQueryFont(dpy, font);
   if (!fs) {
      _mesa_error(NULL, GL_INVALID_VALUE,
		  "Couldn't get font structure information");
      return;
   }

   /* Allocate a bitmap that can fit all characters.  */
   max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
   max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
   max_bm_width = (max_width + 7) / 8;
   max_bm_height = max_height;

   bm = (GLubyte *) malloc((max_bm_width * max_bm_height) * sizeof(GLubyte));
   if (!bm) {
      XFreeFontInfo(NULL, fs, 1);
      _mesa_error(NULL, GL_OUT_OF_MEMORY,
		  "Couldn't allocate bitmap in glXUseXFont()");
      return;
   }

#if 0
   /* get the page info */
   pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
   firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;
   lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;
   rows = fs->max_byte1 - fs->min_byte1 + 1;
   unsigned int first_char, last_char, pages, rows;
#endif

   /* Save the current packing mode for bitmaps.  */
   glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);
   glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);
   glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);
   glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);
   glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
   glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);

   /* Enforce a standard packing mode which is compatible with
      fill_bitmap() from above.  This is actually the default mode,
      except for the (non)alignment.  */
   glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
   glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
   glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
   glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

   pixmap = XCreatePixmap(dpy, win, 10, 10, 1);
   values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
   values.background = WhitePixel(dpy, DefaultScreen(dpy));
   values.font = fs->fid;
   valuemask = GCForeground | GCBackground | GCFont;
   gc = XCreateGC(dpy, pixmap, valuemask, &values);
   XFreePixmap(dpy, pixmap);

#ifdef DEBUG
   if (debug_xfonts)
      dump_font_struct(fs);
#endif

   for (i = 0; i < count; i++) {
      unsigned int width, height, bm_width, bm_height;
      GLfloat x0, y0, dx, dy;
      XCharStruct *ch;
      int x, y;
      unsigned int c = first + i;
      int list = listbase + i;
      int valid;

      /* check on index validity and get the bounds */
      ch = isvalid(fs, c);
      if (!ch) {
	 ch = &fs->max_bounds;
	 valid = 0;
      }
      else {
	 valid = 1;
      }

#ifdef DEBUG
      if (debug_xfonts) {
	 char s[7];
	 sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c);
	 dump_char_struct(ch, s);
      }
#endif

      /* glBitmap()' parameters:
         straight from the glXUseXFont(3) manpage.  */
      width = ch->rbearing - ch->lbearing;
      height = ch->ascent + ch->descent;
      x0 = -ch->lbearing;
      y0 = ch->descent - 0;	/* XXX used to subtract 1 here */
      /* but that caused a conformace failure */
      dx = ch->width;
      dy = 0;

      /* X11's starting point.  */
      x = -ch->lbearing;
      y = ch->ascent;

      /* Round the width to a multiple of eight.  We will use this also
         for the pixmap for capturing the X11 font.  This is slightly
         inefficient, but it makes the OpenGL part real easy.  */
      bm_width = (width + 7) / 8;
      bm_height = height;

      glNewList(list, GL_COMPILE);
      if (valid && (bm_width > 0) && (bm_height > 0)) {

	 memset(bm, '\0', bm_width * bm_height);
	 fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm);

	 glBitmap(width, height, x0, y0, dx, dy, bm);
#ifdef DEBUG
	 if (debug_xfonts) {
	    printf("width/height = %u/%u\n", width, height);
	    printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height);
	    dump_bitmap(bm_width, bm_height, bm);
	 }
#endif
      }
      else {
	 glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL);
      }
      glEndList();
   }

   free(bm);
   XFreeFontInfo(NULL, fs, 1);
   XFreeGC(dpy, gc);

   /* Restore saved packing modes.  */
   glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
   glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
   glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
   glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
   glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
   glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
}
Exemplo n.º 2
0
void GLAPIENTRY
_mesa_PointParameterfv( GLenum pname, const GLfloat *params)
{
    GET_CURRENT_CONTEXT(ctx);

    /* Drivers that support point sprites must also support point parameters.
     * If point parameters aren't supported, then this function shouldn't even
     * exist.
     */
    ASSERT(!(ctx->Extensions.ARB_point_sprite
             || ctx->Extensions.NV_point_sprite)
           || ctx->Extensions.EXT_point_parameters);

    if (!ctx->Extensions.EXT_point_parameters) {
        _mesa_error(ctx, GL_INVALID_OPERATION,
                    "unsupported function called (unsupported extension)");
        return;
    }

    switch (pname) {
    case GL_DISTANCE_ATTENUATION_EXT:
        if (TEST_EQ_3V(ctx->Point.Params, params))
            return;
        FLUSH_VERTICES(ctx, _NEW_POINT);
        COPY_3V(ctx->Point.Params, params);
        ctx->Point._Attenuated = (ctx->Point.Params[0] != 1.0 ||
                                  ctx->Point.Params[1] != 0.0 ||
                                  ctx->Point.Params[2] != 0.0);
        break;
    case GL_POINT_SIZE_MIN_EXT:
        if (params[0] < 0.0F) {
            _mesa_error( ctx, GL_INVALID_VALUE,
                         "glPointParameterf[v]{EXT,ARB}(param)" );
            return;
        }
        if (ctx->Point.MinSize == params[0])
            return;
        FLUSH_VERTICES(ctx, _NEW_POINT);
        ctx->Point.MinSize = params[0];
        break;
    case GL_POINT_SIZE_MAX_EXT:
        if (params[0] < 0.0F) {
            _mesa_error( ctx, GL_INVALID_VALUE,
                         "glPointParameterf[v]{EXT,ARB}(param)" );
            return;
        }
        if (ctx->Point.MaxSize == params[0])
            return;
        FLUSH_VERTICES(ctx, _NEW_POINT);
        ctx->Point.MaxSize = params[0];
        break;
    case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
        if (params[0] < 0.0F) {
            _mesa_error( ctx, GL_INVALID_VALUE,
                         "glPointParameterf[v]{EXT,ARB}(param)" );
            return;
        }
        if (ctx->Point.Threshold == params[0])
            return;
        FLUSH_VERTICES(ctx, _NEW_POINT);
        ctx->Point.Threshold = params[0];
        break;
    case GL_POINT_SPRITE_R_MODE_NV:
        /* This is one area where ARB_point_sprite and NV_point_sprite
        * differ.  In ARB_point_sprite the POINT_SPRITE_R_MODE is
        * always ZERO.  NV_point_sprite adds the S and R modes.
        */
        if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_point_sprite) {
            GLenum value = (GLenum) params[0];
            if (value != GL_ZERO && value != GL_S && value != GL_R) {
                _mesa_error(ctx, GL_INVALID_VALUE,
                            "glPointParameterf[v]{EXT,ARB}(param)");
                return;
            }
            if (ctx->Point.SpriteRMode == value)
                return;
            FLUSH_VERTICES(ctx, _NEW_POINT);
            ctx->Point.SpriteRMode = value;
        }
        else {
            _mesa_error(ctx, GL_INVALID_ENUM,
                        "glPointParameterf[v]{EXT,ARB}(pname)");
            return;
        }
        break;
    case GL_POINT_SPRITE_COORD_ORIGIN:
        /* GL_POINT_SPRITE_COORD_ORIGIN was added to point sprites when the
         * extension was merged into OpenGL 2.0.
         */
        if ((ctx->API == API_OPENGL_COMPAT && ctx->Version >= 20)
                || ctx->API == API_OPENGL_CORE) {
            GLenum value = (GLenum) params[0];
            if (value != GL_LOWER_LEFT && value != GL_UPPER_LEFT) {
                _mesa_error(ctx, GL_INVALID_VALUE,
                            "glPointParameterf[v]{EXT,ARB}(param)");
                return;
            }
            if (ctx->Point.SpriteOrigin == value)
                return;
            FLUSH_VERTICES(ctx, _NEW_POINT);
            ctx->Point.SpriteOrigin = value;
        }
        else {
            _mesa_error(ctx, GL_INVALID_ENUM,
                        "glPointParameterf[v]{EXT,ARB}(pname)");
            return;
        }
        break;
    default:
        _mesa_error( ctx, GL_INVALID_ENUM,
                     "glPointParameterf[v]{EXT,ARB}(pname)" );
        return;
    }

    if (ctx->Driver.PointParameterfv)
        (*ctx->Driver.PointParameterfv)(ctx, pname, params);
}
Exemplo n.º 3
0
/**
 * Bind a program (make it current)
 * \note Called from the GL API dispatcher by both glBindProgramNV
 * and glBindProgramARB.
 */
void GLAPIENTRY
_mesa_BindProgramARB(GLenum target, GLuint id)
{
   struct gl_program *curProg, *newProg;
   GET_CURRENT_CONTEXT(ctx);

   /* Error-check target and get curProg */
   if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
      curProg = &ctx->VertexProgram.Current->Base;
   }
   else if (target == GL_FRAGMENT_PROGRAM_ARB
            && ctx->Extensions.ARB_fragment_program) {
      curProg = &ctx->FragmentProgram.Current->Base;
   }
   else {
      _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramARB(target)");
      return;
   }

   /*
    * Get pointer to new program to bind.
    * NOTE: binding to a non-existant program is not an error.
    * That's supposed to be caught in glBegin.
    */
   if (id == 0) {
      /* Bind a default program */
      newProg = NULL;
      if (target == GL_VERTEX_PROGRAM_ARB)
         newProg = &ctx->Shared->DefaultVertexProgram->Base;
      else
         newProg = &ctx->Shared->DefaultFragmentProgram->Base;
   }
   else {
      /* Bind a user program */
      newProg = _mesa_lookup_program(ctx, id);
      if (!newProg || newProg == &_mesa_DummyProgram) {
         /* allocate a new program now */
         newProg = ctx->Driver.NewProgram(ctx, target, id);
         if (!newProg) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramARB");
            return;
         }
         _mesa_HashInsert(ctx->Shared->Programs, id, newProg);
      }
      else if (newProg->Target != target) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glBindProgramARB(target mismatch)");
         return;
      }
   }

   /** All error checking is complete now **/

   if (curProg->Id == id) {
      /* binding same program - no change */
      return;
   }

   /* signal new program (and its new constants) */
   FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);

   /* bind newProg */
   if (target == GL_VERTEX_PROGRAM_ARB) {
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
                               gl_vertex_program(newProg));
   }
   else if (target == GL_FRAGMENT_PROGRAM_ARB) {
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
                               gl_fragment_program(newProg));
   }

   /* Never null pointers */
   assert(ctx->VertexProgram.Current);
   assert(ctx->FragmentProgram.Current);

   if (ctx->Driver.BindProgram)
      ctx->Driver.BindProgram(ctx, target, newProg);
}
Exemplo n.º 4
0
/**
 * Return pointer-valued state, such as a vertex array pointer.
 *
 * \param pname  names state to be queried
 * \param params  returns the pointer value
 *
 * \sa glGetPointerv().
 *
 * Tries to get the specified pointer via dd_function_table::GetPointerv,
 * otherwise gets the specified pointer from the current context.
 */
void GLAPIENTRY
_mesa_GetPointerv( GLenum pname, GLvoid **params )
{
   GET_CURRENT_CONTEXT(ctx);
   const GLuint clientUnit = ctx->Array.ActiveTexture;
   const char *callerstr;

   if (_mesa_is_desktop_gl(ctx))
      callerstr = "glGetPointerv";
   else
      callerstr = "glGetPointervKHR";

   if (!params)
      return;

   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(ctx, "%s %s\n", callerstr, _mesa_enum_to_string(pname));

   switch (pname) {
      case GL_VERTEX_ARRAY_POINTER:
         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
            goto invalid_pname;
         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Ptr;
         break;
      case GL_NORMAL_ARRAY_POINTER:
         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
            goto invalid_pname;
         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_NORMAL].Ptr;
         break;
      case GL_COLOR_ARRAY_POINTER:
         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
            goto invalid_pname;
         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_COLOR0].Ptr;
         break;
      case GL_SECONDARY_COLOR_ARRAY_POINTER_EXT:
         if (ctx->API != API_OPENGL_COMPAT)
            goto invalid_pname;
         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_COLOR1].Ptr;
         break;
      case GL_FOG_COORDINATE_ARRAY_POINTER_EXT:
         if (ctx->API != API_OPENGL_COMPAT)
            goto invalid_pname;
         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_FOG].Ptr;
         break;
      case GL_INDEX_ARRAY_POINTER:
         if (ctx->API != API_OPENGL_COMPAT)
            goto invalid_pname;
         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Ptr;
         break;
      case GL_TEXTURE_COORD_ARRAY_POINTER:
         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
            goto invalid_pname;
         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_TEX(clientUnit)].Ptr;
         break;
      case GL_EDGE_FLAG_ARRAY_POINTER:
         if (ctx->API != API_OPENGL_COMPAT)
            goto invalid_pname;
         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Ptr;
         break;
      case GL_FEEDBACK_BUFFER_POINTER:
         if (ctx->API != API_OPENGL_COMPAT)
            goto invalid_pname;
         *params = ctx->Feedback.Buffer;
         break;
      case GL_SELECTION_BUFFER_POINTER:
         if (ctx->API != API_OPENGL_COMPAT)
            goto invalid_pname;
         *params = ctx->Select.Buffer;
         break;
      case GL_POINT_SIZE_ARRAY_POINTER_OES:
         if (ctx->API != API_OPENGLES)
            goto invalid_pname;
         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr;
         break;
      case GL_DEBUG_CALLBACK_FUNCTION_ARB:
      case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
         *params = _mesa_get_debug_state_ptr(ctx, pname);
         break;
      default:
         goto invalid_pname;
   }

   return;

invalid_pname:
   _mesa_error( ctx, GL_INVALID_ENUM, "%s", callerstr);
   return;
}
/**
 * New in GL 3.0
 * Clear unsigned integer color buffer (not depth, not stencil).
 */
void GLAPIENTRY
_mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   FLUSH_CURRENT(ctx, 0);

   if (ctx->NewState) {
      _mesa_update_state( ctx );
   }

   switch (buffer) {
   case GL_COLOR:
      {
         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
         if (mask == INVALID_MASK) {
            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
                        drawbuffer);
            return;
         }
         else if (mask && !ctx->RasterDiscard) {
            union gl_color_union clearSave;

            /* save color */
            clearSave = ctx->Color.ClearColor;
            /* set color */
            COPY_4V(ctx->Color.ClearColor.ui, value);
            /* clear buffer(s) */
            ctx->Driver.Clear(ctx, mask);
            /* restore color */
            ctx->Color.ClearColor = clearSave;
         }
      }
      break;
   case GL_DEPTH:
   case GL_STENCIL:
      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
       *
       *     "The result of ClearBuffer is undefined if no conversion between
       *     the type of the specified value and the type of the buffer being
       *     cleared is defined (for example, if ClearBufferiv is called for a
       *     fixed- or floating-point buffer, or if ClearBufferfv is called
       *     for a signed or unsigned integer buffer). This is not an error."
       *
       * In this case we take "undefined" and "not an error" to mean "ignore."
       * Even though we could do something sensible for GL_STENCIL, page 263
       * (page 279 of the PDF) says:
       *
       *     "Only ClearBufferiv should be used to clear stencil buffers."
       *
       * Note that we still need to generate an error for the invalid
       * drawbuffer case (see the GL_STENCIL case in _mesa_ClearBufferiv).
       */
      if (drawbuffer != 0) {
         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferuiv(drawbuffer=%d)",
                     drawbuffer);
         return;
      }
      return;
   default:
      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferuiv(buffer=%s)",
                  _mesa_lookup_enum_by_nr(buffer));
      return;
   }
}
Exemplo n.º 6
0
void GLAPIENTRY
_mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                              GLenum pname, GLint *params )
{
   const struct gl_texture_unit *texUnit;
   struct gl_texture_object *texObj;
   const struct gl_texture_image *img = NULL;
   GLint maxLevels;
   gl_format texFormat;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glGetTexLevelParameteriv(current unit)");
      return;
   }

   texUnit = _mesa_get_current_tex_unit(ctx);

   /* this will catch bad target values */
   maxLevels = _mesa_max_texture_levels(ctx, target);
   if (maxLevels == 0) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glGetTexLevelParameter[if]v(target=0x%x)", target);
      return;
   }

   if (level < 0 || level >= maxLevels) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
      return;
   }

   texObj = _mesa_select_tex_object(ctx, texUnit, target);

   img = _mesa_select_tex_image(ctx, texObj, target, level);
   if (!img || img->TexFormat == MESA_FORMAT_NONE) {
      /* undefined texture image */
      if (pname == GL_TEXTURE_COMPONENTS)
         *params = 1;
      else
         *params = 0;
      return;
   }

   texFormat = img->TexFormat;

   switch (pname) {
      case GL_TEXTURE_WIDTH:
         *params = img->Width;
         break;
      case GL_TEXTURE_HEIGHT:
         *params = img->Height;
         break;
      case GL_TEXTURE_DEPTH:
         *params = img->Depth;
         break;
      case GL_TEXTURE_INTERNAL_FORMAT:
         if (_mesa_is_format_compressed(texFormat)) {
            /* need to return the actual compressed format */
            *params = _mesa_compressed_format_to_glenum(ctx, texFormat);
         }
         else {
	    /* If the true internal format is not compressed but the user
	     * requested a generic compressed format, we have to return the
	     * generic base format that matches.
	     *
	     * From page 119 (page 129 of the PDF) of the OpenGL 1.3 spec:
	     *
	     *     "If no specific compressed format is available,
	     *     internalformat is instead replaced by the corresponding base
	     *     internal format."
	     *
	     * Otherwise just return the user's requested internal format
	     */
	    const GLenum f =
	       _mesa_gl_compressed_format_base_format(img->InternalFormat);

	    *params = (f != 0) ? f : img->InternalFormat;
	 }
         break;
      case GL_TEXTURE_BORDER:
         *params = img->Border;
         break;
      case GL_TEXTURE_RED_SIZE:
      case GL_TEXTURE_GREEN_SIZE:
      case GL_TEXTURE_BLUE_SIZE:
      case GL_TEXTURE_ALPHA_SIZE:
         if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
            *params = _mesa_get_format_bits(texFormat, pname);
         else
            *params = 0;
         break;
      case GL_TEXTURE_INTENSITY_SIZE:
      case GL_TEXTURE_LUMINANCE_SIZE:
         if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) {
            *params = _mesa_get_format_bits(texFormat, pname);
            if (*params == 0) {
               /* intensity or luminance is probably stored as RGB[A] */
               *params = MIN2(_mesa_get_format_bits(texFormat,
                                                    GL_TEXTURE_RED_SIZE),
                              _mesa_get_format_bits(texFormat,
                                                    GL_TEXTURE_GREEN_SIZE));
            }
         }
         else {
            *params = 0;
         }
         break;
      case GL_TEXTURE_DEPTH_SIZE_ARB:
         if (!ctx->Extensions.ARB_depth_texture)
            goto invalid_pname;
         *params = _mesa_get_format_bits(texFormat, pname);
         break;
      case GL_TEXTURE_STENCIL_SIZE_EXT:
         if (!ctx->Extensions.EXT_packed_depth_stencil &&
             !ctx->Extensions.ARB_framebuffer_object)
            goto invalid_pname;
         *params = _mesa_get_format_bits(texFormat, pname);
         break;
      case GL_TEXTURE_SHARED_SIZE:
         if (ctx->Version < 30 &&
             !ctx->Extensions.EXT_texture_shared_exponent)
            goto invalid_pname;
         *params = texFormat == MESA_FORMAT_RGB9_E5_FLOAT ? 5 : 0;
         break;

      /* GL_ARB_texture_compression */
      case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
	 if (_mesa_is_format_compressed(texFormat) &&
             !_mesa_is_proxy_texture(target)) {
            *params = _mesa_format_image_size(texFormat, img->Width,
                                              img->Height, img->Depth);
	 }
	 else {
	    _mesa_error(ctx, GL_INVALID_OPERATION,
			"glGetTexLevelParameter[if]v(pname)");
	 }
         break;
      case GL_TEXTURE_COMPRESSED:
         *params = (GLint) _mesa_is_format_compressed(texFormat);
         break;

      /* GL_ARB_texture_float */
      case GL_TEXTURE_RED_TYPE_ARB:
      case GL_TEXTURE_GREEN_TYPE_ARB:
      case GL_TEXTURE_BLUE_TYPE_ARB:
      case GL_TEXTURE_ALPHA_TYPE_ARB:
      case GL_TEXTURE_LUMINANCE_TYPE_ARB:
      case GL_TEXTURE_INTENSITY_TYPE_ARB:
      case GL_TEXTURE_DEPTH_TYPE_ARB:
         if (!ctx->Extensions.ARB_texture_float)
            goto invalid_pname;
	 if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
	    *params = _mesa_get_format_datatype(texFormat);
	 else
	    *params = GL_NONE;
         break;

      default:
         goto invalid_pname;
   }

   /* no error if we get here */
   return;

invalid_pname:
   _mesa_error(ctx, GL_INVALID_ENUM,
               "glGetTexLevelParameter[if]v(pname=%s)",
               _mesa_lookup_enum_by_nr(pname));
}
Exemplo n.º 7
0
static void GLAPIENTRY
_mesa_GetMapiv( GLenum target, GLenum query, GLint *v )
{
    GET_CURRENT_CONTEXT(ctx);
    struct gl_1d_map *map1d;
    struct gl_2d_map *map2d;
    GLuint i, n;
    GLfloat *data;
    GLuint comps;

    ASSERT_OUTSIDE_BEGIN_END(ctx);

    comps = _mesa_evaluator_components(target);
    if (!comps) {
        _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
        return;
    }

    map1d = get_1d_map(ctx, target);
    map2d = get_2d_map(ctx, target);
    ASSERT(map1d || map2d);

    switch (query) {
    case GL_COEFF:
        if (map1d) {
            data = map1d->Points;
            n = map1d->Order * comps;
        }
        else {
            data = map2d->Points;
            n = map2d->Uorder * map2d->Vorder * comps;
        }
        if (data) {
            for (i=0; i<n; i++) {
                v[i] = IROUND(data[i]);
            }
        }
        break;
    case GL_ORDER:
        if (map1d) {
            v[0] = map1d->Order;
        }
        else {
            v[0] = map2d->Uorder;
            v[1] = map2d->Vorder;
        }
        break;
    case GL_DOMAIN:
        if (map1d) {
            v[0] = IROUND(map1d->u1);
            v[1] = IROUND(map1d->u2);
        }
        else {
            v[0] = IROUND(map2d->u1);
            v[1] = IROUND(map2d->u2);
            v[2] = IROUND(map2d->v1);
            v[3] = IROUND(map2d->v2);
        }
        break;
    default:
        _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
    }
    return;
}
Exemplo n.º 8
0
static void GLAPIENTRY
_mesa_GetnMapivARB( GLenum target, GLenum query, GLsizei bufSize, GLint *v )
{
   GET_CURRENT_CONTEXT(ctx);
   struct gl_1d_map *map1d;
   struct gl_2d_map *map2d;
   GLuint i, n;
   GLfloat *data;
   GLuint comps;
   GLsizei numBytes;

   ASSERT_OUTSIDE_BEGIN_END(ctx);

   comps = _mesa_evaluator_components(target);
   if (!comps) {
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
      return;
   }

   map1d = get_1d_map(ctx, target);
   map2d = get_2d_map(ctx, target);
   ASSERT(map1d || map2d);

   switch (query) {
      case GL_COEFF:
         if (map1d) {
            data = map1d->Points;
            n = map1d->Order * comps;
         }
         else {
            data = map2d->Points;
            n = map2d->Uorder * map2d->Vorder * comps;
         }
	 if (data) {
            numBytes = n * sizeof *v;
            if (bufSize < numBytes)
               goto overflow;
	    for (i=0;i<n;i++) {
	       v[i] = IROUND(data[i]);
	    }
	 }
         break;
      case GL_ORDER:
         if (map1d) {
            numBytes = 1 * sizeof *v;
            if (bufSize < numBytes)
               goto overflow;
            v[0] = map1d->Order;
         }
         else {
            numBytes = 2 * sizeof *v;
            if (bufSize < numBytes)
               goto overflow;
            v[0] = map2d->Uorder;
            v[1] = map2d->Vorder;
         }
         break;
      case GL_DOMAIN:
         if (map1d) {
            numBytes = 2 * sizeof *v;
            if (bufSize < numBytes)
               goto overflow;
            v[0] = IROUND(map1d->u1);
            v[1] = IROUND(map1d->u2);
         }
         else {
            numBytes = 4 * sizeof *v;
            if (bufSize < numBytes)
               goto overflow;
            v[0] = IROUND(map2d->u1);
            v[1] = IROUND(map2d->u2);
            v[2] = IROUND(map2d->v1);
            v[3] = IROUND(map2d->v2);
         }
         break;
      default:
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
   }
   return;

overflow:
   _mesa_error( ctx, GL_INVALID_OPERATION,
               "glGetnMapivARB(out of bounds: bufSize is %d,"
               " but %d bytes are required)", bufSize, numBytes );
}
Exemplo n.º 9
0
/**
 * Blit color, depth or stencil with GL_NEAREST filtering.
 */
static void
blit_nearest(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 srcWidth = ABS(srcX1 - srcX0);
   const GLint dstWidth = ABS(dstX1 - dstX0);
   const GLint srcHeight = ABS(srcY1 - srcY0);
   const GLint dstHeight = ABS(dstY1 - dstY0);

   const GLint srcXpos = MIN2(srcX0, srcX1);
   const GLint srcYpos = MIN2(srcY0, srcY1);
   const GLint dstXpos = MIN2(dstX0, dstX1);
   const GLint dstYpos = MIN2(dstY0, dstY1);

   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);

   GLint dstRow;

   GLint comps, pixelSize;
   GLvoid *srcBuffer, *dstBuffer;
   GLint prevY = -1;

   typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
                                 const GLvoid *srcBuffer, GLvoid *dstBuffer,
                                 GLboolean flip);
   resample_func resampleRow;

   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 blit_nearest()");
      return;
   }

   switch (readRb->DataType) {
   case GL_UNSIGNED_BYTE:
      pixelSize = comps * sizeof(GLubyte);
      break;
   case GL_UNSIGNED_SHORT:
      pixelSize = comps * sizeof(GLushort);
      break;
   case GL_UNSIGNED_INT:
      pixelSize = comps * sizeof(GLuint);
      break;
   case GL_FLOAT:
      pixelSize = comps * sizeof(GLfloat);
      break;
   default:
      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
                    readRb->DataType);
      return;
   }

   /* choose row resampler */
   switch (pixelSize) {
   case 1:
      resampleRow = resample_row_1;
      break;
   case 2:
      resampleRow = resample_row_2;
      break;
   case 4:
      resampleRow = resample_row_4;
      break;
   case 8:
      resampleRow = resample_row_8;
      break;
   case 16:
      resampleRow = resample_row_16;
      break;
   default:
      _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
                    pixelSize);
      return;
   }

   /* allocate the src/dst row buffers */
   srcBuffer = malloc(pixelSize * srcWidth);
   if (!srcBuffer) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
      return;
   }
   dstBuffer = malloc(pixelSize * dstWidth);
   if (!dstBuffer) {
      free(srcBuffer);
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
      return;
   }

   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
      const GLint dstY = dstYpos + dstRow;
      GLint srcRow = (dstRow * srcHeight) / dstHeight;
      GLint srcY;

      ASSERT(srcRow >= 0);
      ASSERT(srcRow < srcHeight);

      if (invertY) {
         srcRow = srcHeight - 1 - srcRow;
      }

      srcY = srcYpos + srcRow;

      /* get pixel row from source and resample to match dest width */
      if (prevY != srcY) {
         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY, srcBuffer);
         (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
         prevY = srcY;
      }

      /* store pixel row in destination */
      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
   }

   free(srcBuffer);
   free(dstBuffer);
}
Exemplo n.º 10
0
/**
 * Clear an rgba color buffer with masking if needed.
 */
static void
clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb,
                  const GLubyte colorMask[4])
{
   const GLint x = ctx->DrawBuffer->_Xmin;
   const GLint y = ctx->DrawBuffer->_Ymin;
   const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
   const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
   const GLuint pixelSize = _mesa_get_format_bytes(rb->Format);
   const GLboolean doMasking = (colorMask[0] == 0 ||
                                colorMask[1] == 0 ||
                                colorMask[2] == 0 ||
                                colorMask[3] == 0);
   const GLfloat (*clearColor)[4] =
      (const GLfloat (*)[4]) ctx->Color.ClearColor.f;
   GLbitfield mapMode = GL_MAP_WRITE_BIT;
   GLubyte *map;
   GLint rowStride;
   GLint i, j;

   if (doMasking) {
      /* we'll need to read buffer values too */
      mapMode |= GL_MAP_READ_BIT;
   }

   /* map dest buffer */
   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
                               mapMode, &map, &rowStride);
   if (!map) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(color)");
      return;
   }

   /* for 1, 2, 4-byte clearing */
#define SIMPLE_TYPE_CLEAR(TYPE)                                         \
   do {                                                                 \
      TYPE pixel, pixelMask;                                            \
      _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, &pixel);     \
      if (doMasking) {                                                  \
         _mesa_pack_colormask(rb->Format, colorMask, &pixelMask);       \
         pixel &= pixelMask;                                            \
         pixelMask = ~pixelMask;                                        \
      }                                                                 \
      for (i = 0; i < height; i++) {                                    \
         TYPE *row = (TYPE *) map;                                      \
         if (doMasking) {                                               \
            for (j = 0; j < width; j++) {                               \
               row[j] = (row[j] & pixelMask) | pixel;                   \
            }                                                           \
         }                                                              \
         else {                                                         \
            for (j = 0; j < width; j++) {                               \
               row[j] = pixel;                                          \
            }                                                           \
         }                                                              \
         map += rowStride;                                              \
      }                                                                 \
   } while (0)


   /* for 3, 6, 8, 12, 16-byte clearing */
#define MULTI_WORD_CLEAR(TYPE, N)                                       \
   do {                                                                 \
      TYPE pixel[N], pixelMask[N];                                      \
      GLuint k;                                                         \
      _mesa_pack_float_rgba_row(rb->Format, 1, clearColor, pixel);      \
      if (doMasking) {                                                  \
         _mesa_pack_colormask(rb->Format, colorMask, pixelMask);        \
         for (k = 0; k < N; k++) {                                      \
            pixel[k] &= pixelMask[k];                                   \
            pixelMask[k] = ~pixelMask[k];                               \
         }                                                              \
      }                                                                 \
      for (i = 0; i < height; i++) {                                    \
         TYPE *row = (TYPE *) map;                                      \
         if (doMasking) {                                               \
            for (j = 0; j < width; j++) {                               \
               for (k = 0; k < N; k++) {                                \
                  row[j * N + k] =                                      \
                     (row[j * N + k] & pixelMask[k]) | pixel[k];        \
               }                                                        \
            }                                                           \
         }                                                              \
         else {                                                         \
            for (j = 0; j < width; j++) {                               \
               for (k = 0; k < N; k++) {                                \
                  row[j * N + k] = pixel[k];                            \
               }                                                        \
            }                                                           \
         }                                                              \
         map += rowStride;                                              \
      }                                                                 \
   } while(0)

   switch (pixelSize) {
   case 1:
      SIMPLE_TYPE_CLEAR(GLubyte);
      break;
   case 2:
      SIMPLE_TYPE_CLEAR(GLushort);
      break;
   case 3:
      MULTI_WORD_CLEAR(GLubyte, 3);
      break;
   case 4:
      SIMPLE_TYPE_CLEAR(GLuint);
      break;
   case 6:
      MULTI_WORD_CLEAR(GLushort, 3);
      break;
   case 8:
      MULTI_WORD_CLEAR(GLuint, 2);
      break;
   case 12:
      MULTI_WORD_CLEAR(GLuint, 3);
      break;
   case 16:
      MULTI_WORD_CLEAR(GLuint, 4);
      break;
   default:
      _mesa_problem(ctx, "bad pixel size in clear_rgba_buffer()");
   }

   /* unmap buffer */
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
Exemplo n.º 11
0
/*
 * This does the work of glMap1[fd].
 */
static void
map1(GLenum target, GLfloat u1, GLfloat u2, GLint ustride,
     GLint uorder, const GLvoid *points, GLenum type )
{
   GET_CURRENT_CONTEXT(ctx);
   GLint k;
   GLfloat *pnts;
   struct gl_1d_map *map = NULL;

   ASSERT_OUTSIDE_BEGIN_END(ctx);
   ASSERT(type == GL_FLOAT || type == GL_DOUBLE);

   if (u1 == u2) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" );
      return;
   }
   if (uorder < 1 || uorder > MAX_EVAL_ORDER) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(order)" );
      return;
   }
   if (!points) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(points)" );
      return;
   }

   k = _mesa_evaluator_components( target );
   if (k == 0) {
      _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
   }

   if (ustride < k) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" );
      return;
   }

   if (ctx->Texture.CurrentUnit != 0) {
      /* See OpenGL 1.2.1 spec, section F.2.13 */
      _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
      return;
   }

   map = get_1d_map(ctx, target);
   if (!map) {
      _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
      return;
   }

   /* make copy of the control points */
   if (type == GL_FLOAT)
      pnts = _mesa_copy_map_points1f(target, ustride, uorder, (GLfloat*) points);
   else
      pnts = _mesa_copy_map_points1d(target, ustride, uorder, (GLdouble*) points);


   FLUSH_VERTICES(ctx, _NEW_EVAL);
   map->Order = uorder;
   map->u1 = u1;
   map->u2 = u2;
   map->du = 1.0F / (u2 - u1);
   if (map->Points)
      FREE( map->Points );
   map->Points = pnts;
}
Exemplo n.º 12
0
Arquivo: readpix.c Projeto: iquiw/xsrc
/**
 * Do error checking of the format/type parameters to glReadPixels and
 * glDrawPixels.
 * \param drawing if GL_TRUE do checking for DrawPixels, else do checking
 *                for ReadPixels.
 * \return GL_TRUE if error detected, GL_FALSE if no errors
 */
GLboolean
_mesa_error_check_format_type(struct gl_context *ctx, GLenum format,
                              GLenum type, GLboolean drawing)
{
    const char *readDraw = drawing ? "Draw" : "Read";
    const GLboolean reading = !drawing;

    /* state validation should have already been done */
    ASSERT(ctx->NewState == 0x0);

    if (ctx->Extensions.EXT_packed_depth_stencil
            && type == GL_UNSIGNED_INT_24_8_EXT
            && format != GL_DEPTH_STENCIL_EXT) {
        _mesa_error(ctx, GL_INVALID_OPERATION,
                    "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw);
        return GL_TRUE;
    }

    /* basic combinations test */
    if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
        _mesa_error(ctx, GL_INVALID_ENUM,
                    "gl%sPixels(format or type)", readDraw);
        return GL_TRUE;
    }

    /* additional checks */
    switch (format) {
    case GL_RG:
    case GL_RED:
    case GL_GREEN:
    case GL_BLUE:
    case GL_ALPHA:
    case GL_LUMINANCE:
    case GL_LUMINANCE_ALPHA:
    case GL_RGB:
    case GL_BGR:
    case GL_RGBA:
    case GL_BGRA:
    case GL_ABGR_EXT:
    case GL_RED_INTEGER_EXT:
    case GL_GREEN_INTEGER_EXT:
    case GL_BLUE_INTEGER_EXT:
    case GL_ALPHA_INTEGER_EXT:
    case GL_RGB_INTEGER_EXT:
    case GL_RGBA_INTEGER_EXT:
    case GL_BGR_INTEGER_EXT:
    case GL_BGRA_INTEGER_EXT:
    case GL_LUMINANCE_INTEGER_EXT:
    case GL_LUMINANCE_ALPHA_INTEGER_EXT:
        if (!drawing) {
            /* reading */
            if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
                _mesa_error(ctx, GL_INVALID_OPERATION,
                            "glReadPixels(no color buffer)");
                return GL_TRUE;
            }
        }
        break;
    case GL_COLOR_INDEX:
        if (drawing) {
            if (ctx->PixelMaps.ItoR.Size == 0 ||
                    ctx->PixelMaps.ItoG.Size == 0 ||
                    ctx->PixelMaps.ItoB.Size == 0) {
                _mesa_error(ctx, GL_INVALID_OPERATION,
                            "glDrawPixels(drawing color index pixels into RGB buffer)");
                return GL_TRUE;
            }
        }
        else {
            /* reading */
            if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
                _mesa_error(ctx, GL_INVALID_OPERATION,
                            "glReadPixels(no color buffer)");
                return GL_TRUE;
            }
            /* We no longer support CI-mode color buffers so trying to read
             * GL_COLOR_INDEX pixels is always an error.
             */
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glReadPixels(color buffer is RGB)");
            return GL_TRUE;
        }
        break;
    case GL_STENCIL_INDEX:
        if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
                (reading && !_mesa_source_buffer_exists(ctx, format))) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "gl%sPixels(no stencil buffer)", readDraw);
            return GL_TRUE;
        }
        break;
    case GL_DEPTH_COMPONENT:
        if ((drawing && !_mesa_dest_buffer_exists(ctx, format))) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "gl%sPixels(no depth buffer)", readDraw);
            return GL_TRUE;
        }
        break;
    case GL_DEPTH_STENCIL_EXT:
        if (!ctx->Extensions.EXT_packed_depth_stencil ||
                type != GL_UNSIGNED_INT_24_8_EXT) {
            _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
            return GL_TRUE;
        }
        if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
                (reading && !_mesa_source_buffer_exists(ctx, format))) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "gl%sPixels(no depth or stencil buffer)", readDraw);
            return GL_TRUE;
        }
        break;
    default:
        /* this should have been caught in _mesa_is_legal_format_type() */
        _mesa_problem(ctx, "unexpected format in _mesa_%sPixels", readDraw);
        return GL_TRUE;
    }

    /* no errors */
    return GL_FALSE;
}
Exemplo n.º 13
0
Arquivo: readpix.c Projeto: iquiw/xsrc
void GLAPIENTRY
_mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
                      GLenum format, GLenum type, GLsizei bufSize,
                      GLvoid *pixels )
{
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

    FLUSH_CURRENT(ctx, 0);

    if (MESA_VERBOSE & VERBOSE_API)
        _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
                    width, height,
                    _mesa_lookup_enum_by_nr(format),
                    _mesa_lookup_enum_by_nr(type),
                    pixels);

    if (width < 0 || height < 0) {
        _mesa_error( ctx, GL_INVALID_VALUE,
                     "glReadPixels(width=%d height=%d)", width, height );
        return;
    }

    if (ctx->NewState)
        _mesa_update_state(ctx);

    if (_mesa_error_check_format_type(ctx, format, type, GL_FALSE)) {
        /* found an error */
        return;
    }

    /* Check that the destination format and source buffer are both
     * integer-valued or both non-integer-valued.
     */
    if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
        const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
        const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
        const GLboolean dstInteger = _mesa_is_integer_format(format);
        if (dstInteger != srcInteger) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glReadPixels(integer / non-integer format mismatch");
            return;
        }
    }

    if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
        _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                    "glReadPixels(incomplete framebuffer)" );
        return;
    }

    if (!_mesa_source_buffer_exists(ctx, format)) {
        _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
        return;
    }

    if (width == 0 || height == 0)
        return; /* nothing to do */

    if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
                                   format, type, bufSize, pixels)) {
        if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glReadPixels(out of bounds PBO access)");
        } else {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glReadnPixelsARB(out of bounds access:"
                        " bufSize (%d) is too small)", bufSize);
        }
        return;
    }

    if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
            _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
        /* buffer is mapped - that's an error */
        _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
        return;
    }

    ctx->Driver.ReadPixels(ctx, x, y, width, height,
                           format, type, &ctx->Pack, pixels);
}
Exemplo n.º 14
0
static void GLAPIENTRY
vbo_exec_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
{
   GET_CURRENT_CONTEXT(ctx);
   GLfloat u, du, v, dv, v1, u1;
   GLint i, j;

   ASSERT_OUTSIDE_BEGIN_END(ctx);

   switch (mode) {
   case GL_POINT:
   case GL_LINE:
   case GL_FILL:
      break;
   default:
      _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
      return;
   }

   /* No effect if vertex maps disabled.
    */
   if (!ctx->Eval.Map2Vertex4 && 
       !ctx->Eval.Map2Vertex3 &&
       !(ctx->VertexProgram._Enabled && ctx->Eval.Map2Attrib[VERT_ATTRIB_POS]))
      return;

   du = ctx->Eval.MapGrid2du;
   dv = ctx->Eval.MapGrid2dv;
   v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
   u1 = ctx->Eval.MapGrid2u1 + i1 * du;

   switch (mode) {
   case GL_POINT:
      CALL_Begin(GET_DISPATCH(), (GL_POINTS));
      for (v=v1,j=j1;j<=j2;j++,v+=dv) {
	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
	    CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
	 }
      }
      CALL_End(GET_DISPATCH(), ());
      break;
   case GL_LINE:
      for (v=v1,j=j1;j<=j2;j++,v+=dv) {
	 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
	    CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
	 }
	 CALL_End(GET_DISPATCH(), ());
      }
      for (u=u1,i=i1;i<=i2;i++,u+=du) {
	 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
	 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
	    CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
	 }
	 CALL_End(GET_DISPATCH(), ());
      }
      break;
   case GL_FILL:
      for (v=v1,j=j1;j<j2;j++,v+=dv) {
	 CALL_Begin(GET_DISPATCH(), (GL_TRIANGLE_STRIP));
	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
	    CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
	    CALL_EvalCoord2f(GET_DISPATCH(), (u, v+dv));
	 }
	 CALL_End(GET_DISPATCH(), ());
      }
      break;
   }
}
Exemplo n.º 15
0
/**
 * Set an integer-valued texture parameter
 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
 */
static GLboolean
set_tex_parameteri(struct gl_context *ctx,
                   struct gl_texture_object *texObj,
                   GLenum pname, const GLint *params)
{
   switch (pname) {
   case GL_TEXTURE_MIN_FILTER:
      if (texObj->Sampler.MinFilter == params[0])
         return GL_FALSE;
      switch (params[0]) {
      case GL_NEAREST:
      case GL_LINEAR:
         flush(ctx);
         texObj->Sampler.MinFilter = params[0];
         return GL_TRUE;
      case GL_NEAREST_MIPMAP_NEAREST:
      case GL_LINEAR_MIPMAP_NEAREST:
      case GL_NEAREST_MIPMAP_LINEAR:
      case GL_LINEAR_MIPMAP_LINEAR:
         if (texObj->Target != GL_TEXTURE_RECTANGLE_NV &&
             texObj->Target != GL_TEXTURE_EXTERNAL_OES) {
            flush(ctx);
            texObj->Sampler.MinFilter = params[0];
            return GL_TRUE;
         }
         /* fall-through */
      default:
         goto invalid_param;
      }
      return GL_FALSE;

   case GL_TEXTURE_MAG_FILTER:
      if (texObj->Sampler.MagFilter == params[0])
         return GL_FALSE;
      switch (params[0]) {
      case GL_NEAREST:
      case GL_LINEAR:
         flush(ctx); /* does not effect completeness */
         texObj->Sampler.MagFilter = params[0];
         return GL_TRUE;
      default:
         goto invalid_param;
      }
      return GL_FALSE;

   case GL_TEXTURE_WRAP_S:
      if (texObj->Sampler.WrapS == params[0])
         return GL_FALSE;
      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
         flush(ctx);
         texObj->Sampler.WrapS = params[0];
         return GL_TRUE;
      }
      return GL_FALSE;

   case GL_TEXTURE_WRAP_T:
      if (texObj->Sampler.WrapT == params[0])
         return GL_FALSE;
      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
         flush(ctx);
         texObj->Sampler.WrapT = params[0];
         return GL_TRUE;
      }
      return GL_FALSE;

   case GL_TEXTURE_WRAP_R:
      if (texObj->Sampler.WrapR == params[0])
         return GL_FALSE;
      if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
         flush(ctx);
         texObj->Sampler.WrapR = params[0];
         return GL_TRUE;
      }
      return GL_FALSE;

   case GL_TEXTURE_BASE_LEVEL:
      if (texObj->BaseLevel == params[0])
         return GL_FALSE;
      if (params[0] < 0 ||
          (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) {
         _mesa_error(ctx, GL_INVALID_VALUE,
                     "glTexParameter(param=%d)", params[0]);
         return GL_FALSE;
      }
      incomplete(ctx, texObj);
      texObj->BaseLevel = params[0];
      return GL_TRUE;

   case GL_TEXTURE_MAX_LEVEL:
      if (texObj->MaxLevel == params[0])
         return GL_FALSE;
      if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glTexParameter(param=%d)", params[0]);
         return GL_FALSE;
      }
      incomplete(ctx, texObj);
      texObj->MaxLevel = params[0];
      return GL_TRUE;

   case GL_GENERATE_MIPMAP_SGIS:
      if (params[0] && texObj->Target == GL_TEXTURE_EXTERNAL_OES)
         goto invalid_param;
      if (texObj->GenerateMipmap != params[0]) {
         /* no flush() */
	 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
	 return GL_TRUE;
      }
      return GL_FALSE;

   case GL_TEXTURE_COMPARE_MODE_ARB:
      if (ctx->Extensions.ARB_shadow) {
         if (texObj->Sampler.CompareMode == params[0])
            return GL_FALSE;
         if (params[0] == GL_NONE ||
             params[0] == GL_COMPARE_R_TO_TEXTURE_ARB) {
            flush(ctx);
            texObj->Sampler.CompareMode = params[0];
            return GL_TRUE;
         }
         goto invalid_param;
      }
      goto invalid_pname;

   case GL_TEXTURE_COMPARE_FUNC_ARB:
      if (ctx->Extensions.ARB_shadow) {
         if (texObj->Sampler.CompareFunc == params[0])
            return GL_FALSE;
         switch (params[0]) {
         case GL_LEQUAL:
         case GL_GEQUAL:
            flush(ctx);
            texObj->Sampler.CompareFunc = params[0];
            return GL_TRUE;
         case GL_EQUAL:
         case GL_NOTEQUAL:
         case GL_LESS:
         case GL_GREATER:
         case GL_ALWAYS:
         case GL_NEVER:
            if (ctx->Extensions.EXT_shadow_funcs) {
               flush(ctx);
               texObj->Sampler.CompareFunc = params[0];
               return GL_TRUE;
            }
            /* fall-through */
         default:
            goto invalid_param;
         }
      }
      goto invalid_pname;

   case GL_DEPTH_TEXTURE_MODE_ARB:
      if (ctx->Extensions.ARB_depth_texture) {
         if (texObj->DepthMode == params[0])
            return GL_FALSE;
         if (params[0] == GL_LUMINANCE ||
             params[0] == GL_INTENSITY ||
             params[0] == GL_ALPHA ||
             (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) {
            flush(ctx);
            texObj->DepthMode = params[0];
            return GL_TRUE;
         }
         goto invalid_param;
      }
      goto invalid_pname;

#if FEATURE_OES_draw_texture
   case GL_TEXTURE_CROP_RECT_OES:
      texObj->CropRect[0] = params[0];
      texObj->CropRect[1] = params[1];
      texObj->CropRect[2] = params[2];
      texObj->CropRect[3] = params[3];
      return GL_TRUE;
#endif

   case GL_TEXTURE_SWIZZLE_R_EXT:
   case GL_TEXTURE_SWIZZLE_G_EXT:
   case GL_TEXTURE_SWIZZLE_B_EXT:
   case GL_TEXTURE_SWIZZLE_A_EXT:
      if (ctx->Extensions.EXT_texture_swizzle) {
         const GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
         const GLint swz = comp_to_swizzle(params[0]);
         if (swz < 0) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glTexParameter(swizzle 0x%x)", params[0]);
            return GL_FALSE;
         }
         ASSERT(comp < 4);

         flush(ctx);
         texObj->Swizzle[comp] = params[0];
         set_swizzle_component(&texObj->_Swizzle, comp, swz);
         return GL_TRUE;
      }
      goto invalid_pname;

   case GL_TEXTURE_SWIZZLE_RGBA_EXT:
      if (ctx->Extensions.EXT_texture_swizzle) {
         GLuint comp;
         flush(ctx);
         for (comp = 0; comp < 4; comp++) {
            const GLint swz = comp_to_swizzle(params[comp]);
            if (swz >= 0) {
               texObj->Swizzle[comp] = params[comp];
               set_swizzle_component(&texObj->_Swizzle, comp, swz);
            }
            else {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "glTexParameter(swizzle 0x%x)", params[comp]);
               return GL_FALSE;
            }
         }
         return GL_TRUE;
      }
      goto invalid_pname;

   case GL_TEXTURE_SRGB_DECODE_EXT:
      if (ctx->Extensions.EXT_texture_sRGB_decode) {
	 GLenum decode = params[0];
	 if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) {
	    if (texObj->Sampler.sRGBDecode != decode) {
	       flush(ctx);
	       texObj->Sampler.sRGBDecode = decode;
	    }
	    return GL_TRUE;
	 }
      }
      goto invalid_pname;

   case GL_TEXTURE_CUBE_MAP_SEAMLESS:
      if (ctx->Extensions.AMD_seamless_cubemap_per_texture) {
         GLenum param = params[0];
         if (param != GL_TRUE && param != GL_FALSE) {
            goto invalid_param;
         }
         if (param != texObj->Sampler.CubeMapSeamless) {
            flush(ctx);
            texObj->Sampler.CubeMapSeamless = param;
         }
         return GL_TRUE;
      }
      goto invalid_pname;

   default:
      goto invalid_pname;
   }

invalid_pname:
   _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)",
               _mesa_lookup_enum_by_nr(pname));
   return GL_FALSE;

invalid_param:
   _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param=%s)",
               _mesa_lookup_enum_by_nr(params[0]));
   return GL_FALSE;
}
Exemplo n.º 16
0
/**
 * Bilinear filtered blit (color only).
 */
static void
blit_linear(struct gl_context *ctx,
            GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
            GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
{
   struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;
   struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];

   const GLint srcWidth = ABS(srcX1 - srcX0);
   const GLint dstWidth = ABS(dstX1 - dstX0);
   const GLint srcHeight = ABS(srcY1 - srcY0);
   const GLint dstHeight = ABS(dstY1 - dstY0);
   const GLfloat dstHeightF = (GLfloat) dstHeight;

   const GLint srcXpos = MIN2(srcX0, srcX1);
   const GLint srcYpos = MIN2(srcY0, srcY1);
   const GLint dstXpos = MIN2(dstX0, dstX1);
   const GLint dstYpos = MIN2(dstY0, dstY1);

   const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
   const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);

   GLint dstRow;

   GLint pixelSize;
   GLvoid *srcBuffer0, *srcBuffer1;
   GLint srcBufferY0 = -1, srcBufferY1 = -1;
   GLvoid *dstBuffer;

   switch (readRb->DataType) {
   case GL_UNSIGNED_BYTE:
      pixelSize = 4 * sizeof(GLubyte);
      break;
   case GL_UNSIGNED_SHORT:
      pixelSize = 4 * sizeof(GLushort);
      break;
   case GL_UNSIGNED_INT:
      pixelSize = 4 * sizeof(GLuint);
      break;
   case GL_FLOAT:
      pixelSize = 4 * sizeof(GLfloat);
      break;
   default:
      _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
                    readRb->DataType);
      return;
   }

   /* Allocate the src/dst row buffers.
    * Keep two adjacent src rows around for bilinear sampling.
    */
   srcBuffer0 = malloc(pixelSize * srcWidth);
   if (!srcBuffer0) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
      return;
   }
   srcBuffer1 = malloc(pixelSize * srcWidth);
   if (!srcBuffer1) {
      free(srcBuffer0);
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
      return;
   }
   dstBuffer = malloc(pixelSize * dstWidth);
   if (!dstBuffer) {
      free(srcBuffer0);
      free(srcBuffer1);
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
      return;
   }

   for (dstRow = 0; dstRow < dstHeight; dstRow++) {
      const GLint dstY = dstYpos + dstRow;
      const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
      GLint srcRow0 = IFLOOR(srcRow);
      GLint srcRow1 = srcRow0 + 1;
      GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */

      ASSERT(srcRow >= 0);
      ASSERT(srcRow < srcHeight);

      if (srcRow1 == srcHeight) {
         /* last row fudge */
         srcRow1 = srcRow0;
         rowWeight = 0.0;
      }

      if (invertY) {
         srcRow0 = srcHeight - 1 - srcRow0;
         srcRow1 = srcHeight - 1 - srcRow1;
      }

      srcY0 = srcYpos + srcRow0;
      srcY1 = srcYpos + srcRow1;

      /* get the two source rows */
      if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
         /* use same source row buffers again */
      }
      else if (srcY0 == srcBufferY1) {
         /* move buffer1 into buffer0 by swapping pointers */
         GLvoid *tmp = srcBuffer0;
         srcBuffer0 = srcBuffer1;
         srcBuffer1 = tmp;
         /* get y1 row */
         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
         srcBufferY0 = srcY0;
         srcBufferY1 = srcY1;
      }
      else {
         /* get both new rows */
         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0, srcBuffer0);
         readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
         srcBufferY0 = srcY0;
         srcBufferY1 = srcY1;
      }

      if (readRb->DataType == GL_UNSIGNED_BYTE) {
         resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
                                dstBuffer, invertX, rowWeight);
      }
      else {
         _mesa_problem(ctx, "Unsupported color channel type in sw blit");
         break;
      }

      /* store pixel row in destination */
      drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
   }

   free(srcBuffer0);
   free(srcBuffer1);
   free(dstBuffer);
}
Exemplo n.º 17
0
/**
 * Set a float-valued texture parameter
 * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
 */
static GLboolean
set_tex_parameterf(struct gl_context *ctx,
                   struct gl_texture_object *texObj,
                   GLenum pname, const GLfloat *params)
{
   switch (pname) {
   case GL_TEXTURE_MIN_LOD:
      if (texObj->Sampler.MinLod == params[0])
         return GL_FALSE;
      flush(ctx);
      texObj->Sampler.MinLod = params[0];
      return GL_TRUE;

   case GL_TEXTURE_MAX_LOD:
      if (texObj->Sampler.MaxLod == params[0])
         return GL_FALSE;
      flush(ctx);
      texObj->Sampler.MaxLod = params[0];
      return GL_TRUE;

   case GL_TEXTURE_PRIORITY:
      flush(ctx);
      texObj->Priority = CLAMP(params[0], 0.0F, 1.0F);
      return GL_TRUE;

   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
      if (ctx->Extensions.EXT_texture_filter_anisotropic) {
         if (texObj->Sampler.MaxAnisotropy == params[0])
            return GL_FALSE;
         if (params[0] < 1.0) {
            _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
            return GL_FALSE;
         }
         flush(ctx);
         /* clamp to max, that's what NVIDIA does */
         texObj->Sampler.MaxAnisotropy = MIN2(params[0],
                                      ctx->Const.MaxTextureMaxAnisotropy);
         return GL_TRUE;
      }
      else {
         static GLuint count = 0;
         if (count++ < 10)
            _mesa_error(ctx, GL_INVALID_ENUM,
                        "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
      }
      return GL_FALSE;

   case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
      if (ctx->Extensions.ARB_shadow_ambient) {
         if (texObj->Sampler.CompareFailValue != params[0]) {
            flush(ctx);
            texObj->Sampler.CompareFailValue = CLAMP(params[0], 0.0F, 1.0F);
            return GL_TRUE;
         }
      }
      else {
         _mesa_error(ctx, GL_INVALID_ENUM,
                    "glTexParameter(pname=GL_TEXTURE_COMPARE_FAIL_VALUE_ARB)");
      }
      return GL_FALSE;

   case GL_TEXTURE_LOD_BIAS:
      /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias */
      if (texObj->Sampler.LodBias != params[0]) {
	 flush(ctx);
	 texObj->Sampler.LodBias = params[0];
	 return GL_TRUE;
      }
      break;

   case GL_TEXTURE_BORDER_COLOR:
      flush(ctx);
      /* ARB_texture_float disables clamping */
      if (ctx->Extensions.ARB_texture_float) {
         texObj->Sampler.BorderColor.f[RCOMP] = params[0];
         texObj->Sampler.BorderColor.f[GCOMP] = params[1];
         texObj->Sampler.BorderColor.f[BCOMP] = params[2];
         texObj->Sampler.BorderColor.f[ACOMP] = params[3];
      } else {
         texObj->Sampler.BorderColor.f[RCOMP] = CLAMP(params[0], 0.0F, 1.0F);
         texObj->Sampler.BorderColor.f[GCOMP] = CLAMP(params[1], 0.0F, 1.0F);
         texObj->Sampler.BorderColor.f[BCOMP] = CLAMP(params[2], 0.0F, 1.0F);
         texObj->Sampler.BorderColor.f[ACOMP] = CLAMP(params[3], 0.0F, 1.0F);
      }
      return GL_TRUE;

   default:
      _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
   }
   return GL_FALSE;
}
Exemplo n.º 18
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);
}
Exemplo n.º 19
0
static void
map2( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
      GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
      const GLvoid *points, GLenum type )
{
    GET_CURRENT_CONTEXT(ctx);
    GLint k;
    GLfloat *pnts;
    struct gl_2d_map *map = NULL;

    ASSERT_OUTSIDE_BEGIN_END(ctx);
    ASSERT(type == GL_FLOAT || type == GL_DOUBLE);

    if (u1==u2) {
        _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" );
        return;
    }

    if (v1==v2) {
        _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" );
        return;
    }

    if (uorder<1 || uorder>MAX_EVAL_ORDER) {
        _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" );
        return;
    }

    if (vorder<1 || vorder>MAX_EVAL_ORDER) {
        _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" );
        return;
    }

    k = _mesa_evaluator_components( target );
    if (k==0) {
        _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
    }

    if (ustride < k) {
        _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" );
        return;
    }
    if (vstride < k) {
        _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" );
        return;
    }

    map = get_2d_map(ctx, target);
    if (!map) {
        _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
        return;
    }

    /* make copy of the control points */
    if (type == GL_FLOAT)
        pnts = _mesa_copy_map_points2f(target, ustride, uorder,
                                       vstride, vorder, (GLfloat*) points);
    else
        pnts = _mesa_copy_map_points2d(target, ustride, uorder,
                                       vstride, vorder, (GLdouble*) points);


    FLUSH_VERTICES(ctx, _NEW_EVAL);
    map->Uorder = uorder;
    map->u1 = u1;
    map->u2 = u2;
    map->du = 1.0F / (u2 - u1);
    map->Vorder = vorder;
    map->v1 = v1;
    map->v2 = v2;
    map->dv = 1.0F / (v2 - v1);
    if (map->Points)
        FREE( map->Points );
    map->Points = pnts;
}
Exemplo n.º 20
0
void GLAPIENTRY
_mesa_GetActiveUniformBlockiv(GLuint program,
			      GLuint uniformBlockIndex,
			      GLenum pname,
			      GLint *params)
{
   GET_CURRENT_CONTEXT(ctx);
   struct gl_shader_program *shProg;
   struct gl_uniform_block *block;
   unsigned i;

   if (!ctx->Extensions.ARB_uniform_buffer_object) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
      return;
   }

   shProg = _mesa_lookup_shader_program_err(ctx, program,
					    "glGetActiveUniformBlockiv");
   if (!shProg)
      return;

   if (uniformBlockIndex >= shProg->NumUniformBlocks) {
      _mesa_error(ctx, GL_INVALID_VALUE,
		  "glGetActiveUniformBlockiv(block index %u >= %u)",
		  uniformBlockIndex, shProg->NumUniformBlocks);
      return;
   }

   block = &shProg->UniformBlocks[uniformBlockIndex];

   switch (pname) {
   case GL_UNIFORM_BLOCK_BINDING:
      params[0] = block->Binding;
      return;

   case GL_UNIFORM_BLOCK_DATA_SIZE:
      params[0] = block->UniformBufferSize;
      return;

   case GL_UNIFORM_BLOCK_NAME_LENGTH:
      params[0] = strlen(block->Name) + 1;
      return;

   case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
      params[0] = block->NumUniforms;
      return;

   case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
      for (i = 0; i < block->NumUniforms; i++) {
	 unsigned offset;
	 params[i] = _mesa_get_uniform_location(ctx, shProg,
						block->Uniforms[i].IndexName,
						&offset);
      }
      return;

   case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
      params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_VERTEX][uniformBlockIndex] != -1;
      return;

   case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER:
      params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_GEOMETRY][uniformBlockIndex] != -1;
      return;

   case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
      params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_FRAGMENT][uniformBlockIndex] != -1;
      return;

   default:
      _mesa_error(ctx, GL_INVALID_ENUM,
		  "glGetActiveUniformBlockiv(pname 0x%x (%s))",
		  pname, _mesa_lookup_enum_by_nr(pname));
      return;
   }
}
Exemplo n.º 21
0
/**
 * Execute a glMaterial call.  Note that if GL_COLOR_MATERIAL is enabled,
 * this may be a (partial) no-op.
 */
static void GLAPIENTRY
vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
{
    GLbitfield updateMats;
    GET_CURRENT_CONTEXT(ctx);

    /* This function should be a no-op when it tries to update material
     * attributes which are currently tracking glColor via glColorMaterial.
     * The updateMats var will be a mask of the MAT_BIT_FRONT/BACK_x bits
     * indicating which material attributes can actually be updated below.
     */
    if (ctx->Light.ColorMaterialEnabled) {
        updateMats = ~ctx->Light._ColorMaterialBitmask;
    }
    else {
        /* GL_COLOR_MATERIAL is disabled so don't skip any material updates */
        updateMats = ALL_MATERIAL_BITS;
    }

    if (ctx->API == API_OPENGL_COMPAT && face == GL_FRONT) {
        updateMats &= FRONT_MATERIAL_BITS;
    }
    else if (ctx->API == API_OPENGL_COMPAT && face == GL_BACK) {
        updateMats &= BACK_MATERIAL_BITS;
    }
    else if (face != GL_FRONT_AND_BACK) {
        _mesa_error(ctx, GL_INVALID_ENUM, "glMaterial(invalid face)");
        return;
    }

    switch (pname) {
    case GL_EMISSION:
        if (updateMats & MAT_BIT_FRONT_EMISSION)
            MAT_ATTR(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, params);
        if (updateMats & MAT_BIT_BACK_EMISSION)
            MAT_ATTR(VBO_ATTRIB_MAT_BACK_EMISSION, 4, params);
        break;
    case GL_AMBIENT:
        if (updateMats & MAT_BIT_FRONT_AMBIENT)
            MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
        if (updateMats & MAT_BIT_BACK_AMBIENT)
            MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
        break;
    case GL_DIFFUSE:
        if (updateMats & MAT_BIT_FRONT_DIFFUSE)
            MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
        if (updateMats & MAT_BIT_BACK_DIFFUSE)
            MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
        break;
    case GL_SPECULAR:
        if (updateMats & MAT_BIT_FRONT_SPECULAR)
            MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, params);
        if (updateMats & MAT_BIT_BACK_SPECULAR)
            MAT_ATTR(VBO_ATTRIB_MAT_BACK_SPECULAR, 4, params);
        break;
    case GL_SHININESS:
        if (*params < 0 || *params > ctx->Const.MaxShininess) {
            _mesa_error(ctx, GL_INVALID_VALUE,
                        "glMaterial(invalid shininess: %f out range [0, %f])",
                        *params, ctx->Const.MaxShininess);
            return;
        }
        if (updateMats & MAT_BIT_FRONT_SHININESS)
            MAT_ATTR(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, params);
        if (updateMats & MAT_BIT_BACK_SHININESS)
            MAT_ATTR(VBO_ATTRIB_MAT_BACK_SHININESS, 1, params);
        break;
    case GL_COLOR_INDEXES:
        if (ctx->API != API_OPENGL_COMPAT) {
            _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
            return;
        }
        if (updateMats & MAT_BIT_FRONT_INDEXES)
            MAT_ATTR(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, params);
        if (updateMats & MAT_BIT_BACK_INDEXES)
            MAT_ATTR(VBO_ATTRIB_MAT_BACK_INDEXES, 3, params);
        break;
    case GL_AMBIENT_AND_DIFFUSE:
        if (updateMats & MAT_BIT_FRONT_AMBIENT)
            MAT_ATTR(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, params);
        if (updateMats & MAT_BIT_FRONT_DIFFUSE)
            MAT_ATTR(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, params);
        if (updateMats & MAT_BIT_BACK_AMBIENT)
            MAT_ATTR(VBO_ATTRIB_MAT_BACK_AMBIENT, 4, params);
        if (updateMats & MAT_BIT_BACK_DIFFUSE)
            MAT_ATTR(VBO_ATTRIB_MAT_BACK_DIFFUSE, 4, params);
        break;
    default:
        _mesa_error(ctx, GL_INVALID_ENUM, "glMaterialfv(pname)");
        return;
    }
}
Exemplo n.º 22
0
void GLAPIENTRY
_mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex,
                                     GLenum pname, GLint *params)
{
   GET_CURRENT_CONTEXT(ctx);
   struct gl_shader_program *shProg;
   struct gl_active_atomic_buffer *ab;
   GLuint i;

   if (!ctx->Extensions.ARB_shader_atomic_counters) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glGetActiveAtomicCounterBufferiv");
      return;
   }

   shProg = _mesa_lookup_shader_program_err(ctx, program,
                                            "glGetActiveAtomicCounterBufferiv");
   if (!shProg)
      return;

   if (bufferIndex >= shProg->NumAtomicBuffers) {
      _mesa_error(ctx, GL_INVALID_VALUE,
                  "glGetActiveAtomicCounterBufferiv(bufferIndex)");
      return;
   }

   ab = &shProg->AtomicBuffers[bufferIndex];

   switch (pname) {
   case GL_ATOMIC_COUNTER_BUFFER_BINDING:
      params[0] = ab->Binding;
      return;
   case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE:
      params[0] = ab->MinimumSize;
      return;
   case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS:
      params[0] = ab->NumUniforms;
      return;
   case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES:
      for (i = 0; i < ab->NumUniforms; ++i)
         params[i] = ab->Uniforms[i];
      return;
   case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER:
      params[0] = ab->StageReferences[MESA_SHADER_VERTEX];
      return;
   case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER:
      params[0] = ab->StageReferences[MESA_SHADER_GEOMETRY];
      return;
   case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER:
      params[0] = ab->StageReferences[MESA_SHADER_FRAGMENT];
      return;
   case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER:
      params[0] = GL_FALSE;
      return;
   case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER:
      params[0] = GL_FALSE;
      return;
   default:
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glGetActiveAtomicCounterBufferiv(pname 0x%x (%s))",
                  pname, _mesa_lookup_enum_by_nr(pname));
      return;
   }
}
/**
 * Clear buffers.
 * 
 * \param mask bit-mask indicating the buffers to be cleared.
 *
 * Flushes the vertices and verifies the parameter. If __struct gl_contextRec::NewState
 * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
 * etc. If the rasterization mode is set to GL_RENDER then requests the driver
 * to clear the buffers, via the dd_function_table::Clear callback.
 */ 
void GLAPIENTRY
_mesa_Clear( GLbitfield mask )
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   FLUSH_CURRENT(ctx, 0);

   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(ctx, "glClear 0x%x\n", mask);

   if (mask & ~(GL_COLOR_BUFFER_BIT |
                GL_DEPTH_BUFFER_BIT |
                GL_STENCIL_BUFFER_BIT |
                GL_ACCUM_BUFFER_BIT)) {
      /* invalid bit set */
      _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
      return;
   }

   /* Accumulation buffers were removed in core contexts, and they never
    * existed in OpenGL ES.
    */
   if ((mask & GL_ACCUM_BUFFER_BIT) != 0
       && (ctx->API == API_OPENGL_CORE || _mesa_is_gles(ctx))) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glClear(GL_ACCUM_BUFFER_BIT)");
      return;
   }

   if (ctx->NewState) {
      _mesa_update_state( ctx );	/* update _Xmin, etc */
   }

   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                  "glClear(incomplete framebuffer)");
      return;
   }

   if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 ||
       ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax ||
       ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax)
      return;

   if (ctx->RasterDiscard)
      return;

   if (ctx->RenderMode == GL_RENDER) {
      GLbitfield bufferMask;

      /* don't clear depth buffer if depth writing disabled */
      if (!ctx->Depth.Mask)
         mask &= ~GL_DEPTH_BUFFER_BIT;

      /* Build the bitmask to send to device driver's Clear function.
       * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
       * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
       * BUFFER_BIT_COLORn flags.
       */
      bufferMask = 0;
      if (mask & GL_COLOR_BUFFER_BIT) {
         GLuint i;
         for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
            bufferMask |= (1 << ctx->DrawBuffer->_ColorDrawBufferIndexes[i]);
         }
      }

      if ((mask & GL_DEPTH_BUFFER_BIT)
          && ctx->DrawBuffer->Visual.haveDepthBuffer) {
         bufferMask |= BUFFER_BIT_DEPTH;
      }

      if ((mask & GL_STENCIL_BUFFER_BIT)
          && ctx->DrawBuffer->Visual.haveStencilBuffer) {
         bufferMask |= BUFFER_BIT_STENCIL;
      }

      if ((mask & GL_ACCUM_BUFFER_BIT)
          && ctx->DrawBuffer->Visual.haveAccumBuffer) {
         bufferMask |= BUFFER_BIT_ACCUM;
      }

      ASSERT(ctx->Driver.Clear);
      ctx->Driver.Clear(ctx, bufferMask);
   }
}
/**
 * Set the current matrix stack.
 *
 * \param mode matrix stack.
 *
 * \sa glMatrixMode().
 *
 * Flushes the vertices, validates the parameter and updates
 * __struct gl_contextRec::CurrentStack and gl_transform_attrib::MatrixMode
 * with the specified matrix stack.
 */
void GLAPIENTRY
_mesa_MatrixMode( GLenum mode )
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (ctx->Transform.MatrixMode == mode && mode != GL_TEXTURE)
      return;
   FLUSH_VERTICES(ctx, _NEW_TRANSFORM);

   switch (mode) {
   case GL_MODELVIEW:
      ctx->CurrentStack = &ctx->ModelviewMatrixStack;
      break;
   case GL_PROJECTION:
      ctx->CurrentStack = &ctx->ProjectionMatrixStack;
      break;
   case GL_TEXTURE:
      /* This error check is disabled because if we're called from
       * glPopAttrib() when the active texture unit is >= MaxTextureCoordUnits
       * we'll generate an unexpected error.
       * From the GL_ARB_vertex_shader spec it sounds like we should instead
       * do error checking in other places when we actually try to access
       * texture matrices beyond MaxTextureCoordUnits.
       */
#if 0
      if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glMatrixMode(invalid tex unit %d)",
                     ctx->Texture.CurrentUnit);
         return;
      }
#endif
      ASSERT(ctx->Texture.CurrentUnit < Elements(ctx->TextureMatrixStack));
      ctx->CurrentStack = &ctx->TextureMatrixStack[ctx->Texture.CurrentUnit];
      break;
   case GL_MATRIX0_NV:
   case GL_MATRIX1_NV:
   case GL_MATRIX2_NV:
   case GL_MATRIX3_NV:
   case GL_MATRIX4_NV:
   case GL_MATRIX5_NV:
   case GL_MATRIX6_NV:
   case GL_MATRIX7_NV:
      if (ctx->API == API_OPENGL && ctx->Extensions.NV_vertex_program) {
         ctx->CurrentStack = &ctx->ProgramMatrixStack[mode - GL_MATRIX0_NV];
      }
      else {
         _mesa_error( ctx,  GL_INVALID_ENUM, "glMatrixMode(mode)" );
         return;
      }
      break;
   case GL_MATRIX0_ARB:
   case GL_MATRIX1_ARB:
   case GL_MATRIX2_ARB:
   case GL_MATRIX3_ARB:
   case GL_MATRIX4_ARB:
   case GL_MATRIX5_ARB:
   case GL_MATRIX6_ARB:
   case GL_MATRIX7_ARB:
      if (ctx->API == API_OPENGL
          && (ctx->Extensions.ARB_vertex_program ||
              ctx->Extensions.ARB_fragment_program)) {
         const GLuint m = mode - GL_MATRIX0_ARB;
         if (m > ctx->Const.MaxProgramMatrices) {
            _mesa_error(ctx, GL_INVALID_ENUM,
                        "glMatrixMode(GL_MATRIX%d_ARB)", m);
            return;
         }
         ctx->CurrentStack = &ctx->ProgramMatrixStack[m];
      }
      else {
         _mesa_error( ctx,  GL_INVALID_ENUM, "glMatrixMode(mode)" );
         return;
      }
      break;
   default:
      _mesa_error( ctx,  GL_INVALID_ENUM, "glMatrixMode(mode)" );
      return;
   }

   ctx->Transform.MatrixMode = mode;
}
/**
 * New in GL 3.0
 * Clear fixed-pt or float color buffer or depth buffer (not stencil).
 */
void GLAPIENTRY
_mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
{
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);

   FLUSH_CURRENT(ctx, 0);

   if (ctx->NewState) {
      _mesa_update_state( ctx );
   }

   switch (buffer) {
   case GL_DEPTH:
      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
       *
       *     "ClearBuffer generates an INVALID VALUE error if buffer is
       *     COLOR and drawbuffer is less than zero, or greater than the
       *     value of MAX DRAW BUFFERS minus one; or if buffer is DEPTH,
       *     STENCIL, or DEPTH STENCIL and drawbuffer is not zero."
       */
      if (drawbuffer != 0) {
         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
                     drawbuffer);
         return;
      }
      else if (ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer && !ctx->RasterDiscard) {
         /* Save current depth clear value, set to 'value', do the
          * depth clear and restore the clear value.
          * XXX in the future we may have a new ctx->Driver.ClearBuffer()
          * hook instead.
          */
         const GLclampd clearSave = ctx->Depth.Clear;
         ctx->Depth.Clear = *value;
         ctx->Driver.Clear(ctx, BUFFER_BIT_DEPTH);
         ctx->Depth.Clear = clearSave;
      }
      /* clear depth buffer to value */
      break;
   case GL_COLOR:
      {
         const GLbitfield mask = make_color_buffer_mask(ctx, drawbuffer);
         if (mask == INVALID_MASK) {
            _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
                        drawbuffer);
            return;
         }
         else if (mask && !ctx->RasterDiscard) {
            union gl_color_union clearSave;

            /* save color */
            clearSave = ctx->Color.ClearColor;
            /* set color */
            COPY_4V(ctx->Color.ClearColor.f, value);
            /* clear buffer(s) */
            ctx->Driver.Clear(ctx, mask);
            /* restore color */
            ctx->Color.ClearColor = clearSave;
         }
      }
      break;
   case GL_STENCIL:
      /* Page 264 (page 280 of the PDF) of the OpenGL 3.0 spec says:
       *
       *     "The result of ClearBuffer is undefined if no conversion between
       *     the type of the specified value and the type of the buffer being
       *     cleared is defined (for example, if ClearBufferiv is called for a
       *     fixed- or floating-point buffer, or if ClearBufferfv is called
       *     for a signed or unsigned integer buffer). This is not an error."
       *
       * In this case we take "undefined" and "not an error" to mean "ignore."
       * Note that we still need to generate an error for the invalid
       * drawbuffer case (see the GL_DEPTH case above).
       */
      if (drawbuffer != 0) {
         _mesa_error(ctx, GL_INVALID_VALUE, "glClearBufferfv(drawbuffer=%d)",
                     drawbuffer);
         return;
      }
      return;
   default:
      _mesa_error(ctx, GL_INVALID_ENUM, "glClearBufferfv(buffer=%s)",
                  _mesa_lookup_enum_by_nr(buffer));
      return;
   }
}
Exemplo n.º 26
0
void GLAPIENTRY
_mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
{
   struct gl_texture_object *obj;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   obj = get_texobj(ctx, target, GL_TRUE);
   if (!obj)
      return;

   _mesa_lock_texture(ctx, obj);
   switch (pname) {
      case GL_TEXTURE_MAG_FILTER:
	 *params = ENUM_TO_FLOAT(obj->Sampler.MagFilter);
	 break;
      case GL_TEXTURE_MIN_FILTER:
         *params = ENUM_TO_FLOAT(obj->Sampler.MinFilter);
         break;
      case GL_TEXTURE_WRAP_S:
         *params = ENUM_TO_FLOAT(obj->Sampler.WrapS);
         break;
      case GL_TEXTURE_WRAP_T:
         *params = ENUM_TO_FLOAT(obj->Sampler.WrapT);
         break;
      case GL_TEXTURE_WRAP_R:
         *params = ENUM_TO_FLOAT(obj->Sampler.WrapR);
         break;
      case GL_TEXTURE_BORDER_COLOR:
         if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
            _mesa_update_state_locked(ctx);
         if (ctx->Color._ClampFragmentColor) {
            params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
            params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
            params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
            params[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
         }
         else {
            params[0] = obj->Sampler.BorderColor.f[0];
            params[1] = obj->Sampler.BorderColor.f[1];
            params[2] = obj->Sampler.BorderColor.f[2];
            params[3] = obj->Sampler.BorderColor.f[3];
         }
         break;
      case GL_TEXTURE_RESIDENT:
         *params = 1.0F;
         break;
      case GL_TEXTURE_PRIORITY:
         *params = obj->Priority;
         break;
      case GL_TEXTURE_MIN_LOD:
         *params = obj->Sampler.MinLod;
         break;
      case GL_TEXTURE_MAX_LOD:
         *params = obj->Sampler.MaxLod;
         break;
      case GL_TEXTURE_BASE_LEVEL:
         *params = (GLfloat) obj->BaseLevel;
         break;
      case GL_TEXTURE_MAX_LEVEL:
         *params = (GLfloat) obj->MaxLevel;
         break;
      case GL_TEXTURE_MAX_ANISOTROPY_EXT:
         if (!ctx->Extensions.EXT_texture_filter_anisotropic)
            goto invalid_pname;
         *params = obj->Sampler.MaxAnisotropy;
         break;
      case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
         if (!ctx->Extensions.ARB_shadow_ambient)
            goto invalid_pname;
         *params = obj->Sampler.CompareFailValue;
         break;
      case GL_GENERATE_MIPMAP_SGIS:
	 *params = (GLfloat) obj->GenerateMipmap;
         break;
      case GL_TEXTURE_COMPARE_MODE_ARB:
         if (!ctx->Extensions.ARB_shadow)
            goto invalid_pname;
         *params = (GLfloat) obj->Sampler.CompareMode;
         break;
      case GL_TEXTURE_COMPARE_FUNC_ARB:
         if (!ctx->Extensions.ARB_shadow)
            goto invalid_pname;
         *params = (GLfloat) obj->Sampler.CompareFunc;
         break;
      case GL_DEPTH_TEXTURE_MODE_ARB:
         if (!ctx->Extensions.ARB_depth_texture)
            goto invalid_pname;
         *params = (GLfloat) obj->DepthMode;
         break;
      case GL_TEXTURE_LOD_BIAS:
         *params = obj->Sampler.LodBias;
         break;
#if FEATURE_OES_draw_texture
      case GL_TEXTURE_CROP_RECT_OES:
         params[0] = obj->CropRect[0];
         params[1] = obj->CropRect[1];
         params[2] = obj->CropRect[2];
         params[3] = obj->CropRect[3];
         break;
#endif

      case GL_TEXTURE_SWIZZLE_R_EXT:
      case GL_TEXTURE_SWIZZLE_G_EXT:
      case GL_TEXTURE_SWIZZLE_B_EXT:
      case GL_TEXTURE_SWIZZLE_A_EXT:
         if (!ctx->Extensions.EXT_texture_swizzle)
            goto invalid_pname;
         *params = (GLfloat) obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
         break;

      case GL_TEXTURE_SWIZZLE_RGBA_EXT:
         if (!ctx->Extensions.EXT_texture_swizzle) {
            goto invalid_pname;
         }
         else {
            GLuint comp;
            for (comp = 0; comp < 4; comp++) {
               params[comp] = (GLfloat) obj->Swizzle[comp];
            }
         }
         break;

      case GL_TEXTURE_CUBE_MAP_SEAMLESS:
         if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
            goto invalid_pname;
         *params = (GLfloat) obj->Sampler.CubeMapSeamless;
         break;

      case GL_TEXTURE_IMMUTABLE_FORMAT:
         if (!ctx->Extensions.ARB_texture_storage)
            goto invalid_pname;
         *params = (GLfloat) obj->Immutable;
         break;

      default:
         goto invalid_pname;
   }

   /* no error if we get here */
   _mesa_unlock_texture(ctx, obj);
   return;

invalid_pname:
   _mesa_unlock_texture(ctx, obj);
   _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", pname);
}
Exemplo n.º 27
0
void GLAPIENTRY
_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
                       const GLvoid *string)
{
   struct gl_program *base;
   bool failed;
   GET_CURRENT_CONTEXT(ctx);

   FLUSH_VERTICES(ctx, _NEW_PROGRAM);

   if (!ctx->Extensions.ARB_vertex_program
       && !ctx->Extensions.ARB_fragment_program) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()");
      return;
   }

   if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
      return;
   }

   if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
      struct gl_vertex_program *prog = ctx->VertexProgram.Current;
      _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);

      base = & prog->Base;
   }
   else if (target == GL_FRAGMENT_PROGRAM_ARB
            && ctx->Extensions.ARB_fragment_program) {
      struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
      _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);

      base = & prog->Base;
   }
   else {
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
      return;
   }

   failed = ctx->Program.ErrorPos != -1;

   if (!failed) {
      /* finally, give the program to the driver for translation/checking */
      if (!ctx->Driver.ProgramStringNotify(ctx, target, base)) {
         failed = true;
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glProgramStringARB(rejected by driver");
      }
   }

   if (ctx->_Shader->Flags & GLSL_DUMP) {
      const char *shader_type =
         target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";

      fprintf(stderr, "ARB_%s_program source for program %d:\n",
              shader_type, base->Id);
      fprintf(stderr, "%s\n", (const char *) string);

      if (failed) {
         fprintf(stderr, "ARB_%s_program %d failed to compile.\n",
                 shader_type, base->Id);
      } else {
         fprintf(stderr, "Mesa IR for ARB_%s_program %d:\n",
                 shader_type, base->Id);
         _mesa_print_program(base);
         fprintf(stderr, "\n");
      }
      fflush(stderr);
   }

   /* Capture vp-*.shader_test/fp-*.shader_test files. */
   const char *capture_path = _mesa_get_shader_capture_path();
   if (capture_path != NULL) {
      FILE *file;
      char filename[PATH_MAX];
      const char *shader_type =
         target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";

      _mesa_snprintf(filename, sizeof(filename), "%s/%cp-%u.shader_test",
                     capture_path, shader_type[0], base->Id);
      file = fopen(filename, "w");
      if (file) {
         fprintf(file,
                 "[require]\nGL_ARB_%s_program\n\n[%s program]\n%s\n",
                 shader_type, shader_type, (const char *) string);
         fclose(file);
      } else {
         _mesa_warning(ctx, "Failed to open %s", filename);
      }
   }
}
Exemplo n.º 28
0
void GLAPIENTRY
_mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
{
   struct gl_texture_object *obj;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   obj = get_texobj(ctx, target, GL_TRUE);
   if (!obj)
      return;

   _mesa_lock_texture(ctx, obj);
   switch (pname) {
      case GL_TEXTURE_MAG_FILTER:
         *params = (GLint) obj->Sampler.MagFilter;
         break;
      case GL_TEXTURE_MIN_FILTER:
         *params = (GLint) obj->Sampler.MinFilter;
         break;
      case GL_TEXTURE_WRAP_S:
         *params = (GLint) obj->Sampler.WrapS;
         break;
      case GL_TEXTURE_WRAP_T:
         *params = (GLint) obj->Sampler.WrapT;
         break;
      case GL_TEXTURE_WRAP_R:
         *params = (GLint) obj->Sampler.WrapR;
         break;
      case GL_TEXTURE_BORDER_COLOR:
         {
            GLfloat b[4];
            b[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F);
            b[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F);
            b[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F);
            b[3] = CLAMP(obj->Sampler.BorderColor.f[3], 0.0F, 1.0F);
            params[0] = FLOAT_TO_INT(b[0]);
            params[1] = FLOAT_TO_INT(b[1]);
            params[2] = FLOAT_TO_INT(b[2]);
            params[3] = FLOAT_TO_INT(b[3]);
         }
         break;
      case GL_TEXTURE_RESIDENT:
         *params = 1;
         break;
      case GL_TEXTURE_PRIORITY:
         *params = FLOAT_TO_INT(obj->Priority);
         break;
      case GL_TEXTURE_MIN_LOD:
         *params = (GLint) obj->Sampler.MinLod;
         break;
      case GL_TEXTURE_MAX_LOD:
         *params = (GLint) obj->Sampler.MaxLod;
         break;
      case GL_TEXTURE_BASE_LEVEL:
         *params = obj->BaseLevel;
         break;
      case GL_TEXTURE_MAX_LEVEL:
         *params = obj->MaxLevel;
         break;
      case GL_TEXTURE_MAX_ANISOTROPY_EXT:
         if (!ctx->Extensions.EXT_texture_filter_anisotropic)
            goto invalid_pname;
         *params = (GLint) obj->Sampler.MaxAnisotropy;
         break;
      case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
         if (!ctx->Extensions.ARB_shadow_ambient)
            goto invalid_pname;
         *params = (GLint) FLOAT_TO_INT(obj->Sampler.CompareFailValue);
         break;
      case GL_GENERATE_MIPMAP_SGIS:
	 *params = (GLint) obj->GenerateMipmap;
         break;
      case GL_TEXTURE_COMPARE_MODE_ARB:
         if (!ctx->Extensions.ARB_shadow)
            goto invalid_pname;
         *params = (GLint) obj->Sampler.CompareMode;
         break;
      case GL_TEXTURE_COMPARE_FUNC_ARB:
         if (!ctx->Extensions.ARB_shadow)
            goto invalid_pname;
         *params = (GLint) obj->Sampler.CompareFunc;
         break;
      case GL_DEPTH_TEXTURE_MODE_ARB:
         if (!ctx->Extensions.ARB_depth_texture)
            goto invalid_pname;
         *params = (GLint) obj->DepthMode;
         break;
      case GL_TEXTURE_LOD_BIAS:
         *params = (GLint) obj->Sampler.LodBias;
         break;
#if FEATURE_OES_draw_texture
      case GL_TEXTURE_CROP_RECT_OES:
         params[0] = obj->CropRect[0];
         params[1] = obj->CropRect[1];
         params[2] = obj->CropRect[2];
         params[3] = obj->CropRect[3];
         break;
#endif
      case GL_TEXTURE_SWIZZLE_R_EXT:
      case GL_TEXTURE_SWIZZLE_G_EXT:
      case GL_TEXTURE_SWIZZLE_B_EXT:
      case GL_TEXTURE_SWIZZLE_A_EXT:
         if (!ctx->Extensions.EXT_texture_swizzle)
            goto invalid_pname;
         *params = obj->Swizzle[pname - GL_TEXTURE_SWIZZLE_R_EXT];
         break;

      case GL_TEXTURE_SWIZZLE_RGBA_EXT:
         if (!ctx->Extensions.EXT_texture_swizzle)
            goto invalid_pname;
         COPY_4V(params, obj->Swizzle);
         break;

      case GL_TEXTURE_CUBE_MAP_SEAMLESS:
         if (!ctx->Extensions.AMD_seamless_cubemap_per_texture)
            goto invalid_pname;
         *params = (GLint) obj->Sampler.CubeMapSeamless;
         break;

      case GL_TEXTURE_IMMUTABLE_FORMAT:
         if (!ctx->Extensions.ARB_texture_storage)
            goto invalid_pname;
         *params = (GLint) obj->Immutable;
         break;

      case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
         if (!ctx->Extensions.OES_EGL_image_external)
            goto invalid_pname;
         *params = obj->RequiredTextureImageUnits;
         break;

      default:
         goto invalid_pname;
   }

   /* no error if we get here */
   _mesa_unlock_texture(ctx, obj);
   return;

invalid_pname:
   _mesa_unlock_texture(ctx, obj);
   _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname);
}
Exemplo n.º 29
0
void GLAPIENTRY
_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
{
   const struct gl_program_constants *limits;
   struct gl_program *prog;
   GET_CURRENT_CONTEXT(ctx);

   if (target == GL_VERTEX_PROGRAM_ARB
       && ctx->Extensions.ARB_vertex_program) {
      prog = &(ctx->VertexProgram.Current->Base);
      limits = &ctx->Const.Program[MESA_SHADER_VERTEX];
   }
   else if (target == GL_FRAGMENT_PROGRAM_ARB
            && ctx->Extensions.ARB_fragment_program) {
      prog = &(ctx->FragmentProgram.Current->Base);
      limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT];
   }
   else {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
      return;
   }

   assert(prog);
   assert(limits);

   /* Queries supported for both vertex and fragment programs */
   switch (pname) {
      case GL_PROGRAM_LENGTH_ARB:
         *params
            = prog->String ? (GLint) strlen((char *) prog->String) : 0;
         return;
      case GL_PROGRAM_FORMAT_ARB:
         *params = prog->Format;
         return;
      case GL_PROGRAM_BINDING_ARB:
         *params = prog->Id;
         return;
      case GL_PROGRAM_INSTRUCTIONS_ARB:
         *params = prog->NumInstructions;
         return;
      case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
         *params = limits->MaxInstructions;
         return;
      case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
         *params = prog->NumNativeInstructions;
         return;
      case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
         *params = limits->MaxNativeInstructions;
         return;
      case GL_PROGRAM_TEMPORARIES_ARB:
         *params = prog->NumTemporaries;
         return;
      case GL_MAX_PROGRAM_TEMPORARIES_ARB:
         *params = limits->MaxTemps;
         return;
      case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
         *params = prog->NumNativeTemporaries;
         return;
      case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
         *params = limits->MaxNativeTemps;
         return;
      case GL_PROGRAM_PARAMETERS_ARB:
         *params = prog->NumParameters;
         return;
      case GL_MAX_PROGRAM_PARAMETERS_ARB:
         *params = limits->MaxParameters;
         return;
      case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
         *params = prog->NumNativeParameters;
         return;
      case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
         *params = limits->MaxNativeParameters;
         return;
      case GL_PROGRAM_ATTRIBS_ARB:
         *params = prog->NumAttributes;
         return;
      case GL_MAX_PROGRAM_ATTRIBS_ARB:
         *params = limits->MaxAttribs;
         return;
      case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
         *params = prog->NumNativeAttributes;
         return;
      case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
         *params = limits->MaxNativeAttribs;
         return;
      case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
         *params = prog->NumAddressRegs;
         return;
      case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
         *params = limits->MaxAddressRegs;
         return;
      case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
         *params = prog->NumNativeAddressRegs;
         return;
      case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
         *params = limits->MaxNativeAddressRegs;
         return;
      case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
         *params = limits->MaxLocalParams;
         return;
      case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
         *params = limits->MaxEnvParams;
         return;
      case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
         /*
          * XXX we may not really need a driver callback here.
          * If the number of native instructions, registers, etc. used
          * are all below the maximums, we could return true.
          * The spec says that even if this query returns true, there's
          * no guarantee that the program will run in hardware.
          */
         if (prog->Id == 0) {
            /* default/null program */
            *params = GL_FALSE;
         }
	 else if (ctx->Driver.IsProgramNative) {
            /* ask the driver */
	    *params = ctx->Driver.IsProgramNative( ctx, target, prog );
         }
	 else {
            /* probably running in software */
	    *params = GL_TRUE;
         }
         return;
      default:
         /* continue with fragment-program only queries below */
         break;
   }

   /*
    * The following apply to fragment programs only (at this time)
    */
   if (target == GL_FRAGMENT_PROGRAM_ARB) {
      const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
      switch (pname) {
         case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
            *params = fp->Base.NumNativeAluInstructions;
            return;
         case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
            *params = fp->Base.NumAluInstructions;
            return;
         case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
            *params = fp->Base.NumTexInstructions;
            return;
         case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
            *params = fp->Base.NumNativeTexInstructions;
            return;
         case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
            *params = fp->Base.NumTexIndirections;
            return;
         case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
            *params = fp->Base.NumNativeTexIndirections;
            return;
         case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
            *params = limits->MaxAluInstructions;
            return;
         case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
            *params = limits->MaxNativeAluInstructions;
            return;
         case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
            *params = limits->MaxTexInstructions;
            return;
         case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
            *params = limits->MaxNativeTexInstructions;
            return;
         case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
            *params = limits->MaxTexIndirections;
            return;
         case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
            *params = limits->MaxNativeTexIndirections;
            return;
         default:
            _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
            return;
      }
   } else {
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
      return;
   }
}
Exemplo n.º 30
0
void
_mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
{
   GET_CURRENT_CONTEXT(ctx);
   GLint i = (GLint) (light - GL_LIGHT0);
   struct gl_light *l = &ctx->Light.Light[i];

   if (i < 0 || i >= (GLint) ctx->Const.MaxLights) {
      _mesa_error( ctx, GL_INVALID_ENUM, "glLight" );
      return;
   }

   switch (pname) {
   case GL_AMBIENT:
      if (TEST_EQ_4V(l->Ambient, params))
	 return;
      FLUSH_VERTICES(ctx, _NEW_LIGHT);
      COPY_4V( l->Ambient, params );
      break;
   case GL_DIFFUSE:
      if (TEST_EQ_4V(l->Diffuse, params))
	 return;
      FLUSH_VERTICES(ctx, _NEW_LIGHT);
      COPY_4V( l->Diffuse, params );
      break;
   case GL_SPECULAR:
      if (TEST_EQ_4V(l->Specular, params))
	 return;
      FLUSH_VERTICES(ctx, _NEW_LIGHT);
      COPY_4V( l->Specular, params );
      break;
   case GL_POSITION: {
      GLfloat tmp[4];
      /* transform position by ModelView matrix */
      TRANSFORM_POINT( tmp, ctx->ModelView.m, params );
      if (TEST_EQ_4V(l->EyePosition, tmp))
	 return;
      FLUSH_VERTICES(ctx, _NEW_LIGHT);
      COPY_4V(l->EyePosition, tmp);
      if (l->EyePosition[3] != 0.0F)
	 l->_Flags |= LIGHT_POSITIONAL;
      else
	 l->_Flags &= ~LIGHT_POSITIONAL;
      break;
   }
   case GL_SPOT_DIRECTION: {
      GLfloat tmp[4];
      /* transform direction by inverse modelview */
      if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
	 _math_matrix_analyse( &ctx->ModelView );
      }
      TRANSFORM_NORMAL( tmp, params, ctx->ModelView.inv );
      if (TEST_EQ_3V(l->EyeDirection, tmp))
	 return;
      FLUSH_VERTICES(ctx, _NEW_LIGHT);
      COPY_3V(l->EyeDirection, tmp);
      break;
   }
   case GL_SPOT_EXPONENT:
      if (params[0]<0.0 || params[0]>128.0) {
	 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
	 return;
      }
      if (l->SpotExponent == params[0])
	 return;
      FLUSH_VERTICES(ctx, _NEW_LIGHT);
      l->SpotExponent = params[0];
      _mesa_invalidate_spot_exp_table( l );
      break;
   case GL_SPOT_CUTOFF:
      if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
	 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
	 return;
      }
      if (l->SpotCutoff == params[0])
	 return;
      FLUSH_VERTICES(ctx, _NEW_LIGHT);
      l->SpotCutoff = params[0];
      l->_CosCutoff = (GLfloat) cos(params[0]*DEG2RAD);
      if (l->_CosCutoff < 0)
	 l->_CosCutoff = 0;
      if (l->SpotCutoff != 180.0F)
	 l->_Flags |= LIGHT_SPOT;
      else
	 l->_Flags &= ~LIGHT_SPOT;
      break;
   case GL_CONSTANT_ATTENUATION:
      if (params[0]<0.0) {
	 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
	 return;
      }
      if (l->ConstantAttenuation == params[0])
	 return;
      FLUSH_VERTICES(ctx, _NEW_LIGHT);
      l->ConstantAttenuation = params[0];
      break;
   case GL_LINEAR_ATTENUATION:
      if (params[0]<0.0) {
	 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
	 return;
      }
      if (l->LinearAttenuation == params[0])
	 return;
      FLUSH_VERTICES(ctx, _NEW_LIGHT);
      l->LinearAttenuation = params[0];
      break;
   case GL_QUADRATIC_ATTENUATION:
      if (params[0]<0.0) {
	 _mesa_error( ctx, GL_INVALID_VALUE, "glLight" );
	 return;
      }
      if (l->QuadraticAttenuation == params[0])
	 return;
      FLUSH_VERTICES(ctx, _NEW_LIGHT);
      l->QuadraticAttenuation = params[0];
      break;
   default:
      _mesa_error( ctx, GL_INVALID_ENUM, "glLight" );
      return;
   }

   if (ctx->Driver.Lightfv)
      ctx->Driver.Lightfv( ctx, light, pname, params );
}