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); }
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); }
/** * 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); }
/** * 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; } }
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)); }
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; }
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 ); }
/** * 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); }
/** * 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); }
/* * 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; }
/** * 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; }
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); }
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; } }
/** * 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; }
/** * 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); }
/** * 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; }
/** * 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); }
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; }
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; } }
/** * 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; } }
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; } }
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); }
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); } } }
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); }
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; } }
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 ); }