void _pl_h_set_position (S___(Plotter *_plotter)) { int xnew, ynew; /* if plotter's pen position doesn't agree with what it should be, adjust it */ xnew = IROUND(XD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y)); ynew = IROUND(YD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y)); if (_plotter->hpgl_position_is_unknown == true || xnew != _plotter->hpgl_pos.x || ynew != _plotter->hpgl_pos.y) { if (_plotter->hpgl_pendown == true) { sprintf (_plotter->data->page->point, "PU;PA%d,%d;", xnew, ynew); _plotter->hpgl_pendown = false; } else sprintf (_plotter->data->page->point, "PA%d,%d;", xnew, ynew); _update_buffer (_plotter->data->page); /* update our knowledge of pen position */ _plotter->hpgl_position_is_unknown = false; _plotter->hpgl_pos.x = xnew; _plotter->hpgl_pos.y = ynew; } }
/* * Execute glDrawPixels */ void GLAPIENTRY _mesa_DrawPixels( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" ); return; } if (ctx->NewState) { _mesa_update_state(ctx); } if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels (invalid fragment program)"); return; } if (error_check_format_type(ctx, format, type, GL_TRUE)) { /* found an error */ return; } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glDrawPixels(incomplete framebuffer)" ); return; } if (!ctx->Current.RasterPosValid) { return; } if (ctx->RenderMode == GL_RENDER) { /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ GLint x = IROUND(ctx->Current.RasterPos[0]); GLint y = IROUND(ctx->Current.RasterPos[1]); ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type, &ctx->Unpack, pixels); } else if (ctx->RenderMode == GL_FEEDBACK) { /* Feedback the current raster pos info */ FLUSH_CURRENT( ctx, 0 ); FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterIndex, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } }
void GetPulsePoTLen(long FullPoTLen, int * PulsePoTLen, int * PulseOverlap) { // This routine, given the time axis length of a WU in bins and data available // in the PoTInfo struct, will calculate how many time bins to pass the pulse // detectors for the given time axis length. Time axis length in seconds is // is constant, while length in bins is inversely proportional to FFT length. // If slew rate is so low that, over the duration of the entire WU, // we do not cover the number of beams passed to each call of the // pulse finders then assume that we will be passing the entire PoT // to the pulse finders. This also takes care of the case where slew // rate is zero. Otherwise, calculate that portion of the PoT that // we will be passing. // NOTE: the code calling this routine may be concerned with either pulse finding // or triplet finding. There may be different max and/or min PoT length constraints // between these 2 algorithms. Thus, this routine just returns the length that // will contain PoTInfo.PulseBeams worth of data. It is up to the calling code // to then apply any length constaints. double BinRate, // function of time resolution and slew rate BinsPerBeam; // function of time res, slew rate, and beam width // jeffc - the following line in temporary. Pulse beams will go into the // analysis config. //PoTInfo.PulseBeams = 1.0; BinRate = FullPoTLen / PoTInfo.WUDuration; // in bins/second if(PoTInfo.BeamRate * PoTInfo.WUDuration < PoTInfo.PulseBeams) { BinsPerBeam = (float)FullPoTLen; // slow slew - pass FullPoT } else { BinsPerBeam = BinRate / PoTInfo.BeamRate; // we will pass a portion of FullPoT } *PulsePoTLen = IROUND(BinsPerBeam * PoTInfo.PulseBeams); // in bins if(*PulsePoTLen > FullPoTLen) { *PulsePoTLen = FullPoTLen; // pulse PoT longer than full PoT } // ... so pass as much as we can // ... ie the full PoT *PulseOverlap = IROUND(BinsPerBeam * PoTInfo.PulseOverlapFactor); // in bins #ifdef DEBUG_POT fprintf(stderr, "BinRate = %f\n", BinRate); fprintf(stderr, "BinsPerBeam = %f\n", BinsPerBeam); #endif }
void _pl_x_paint_point (S___(Plotter *_plotter)) { double xx, yy; int ix, iy; plColor oldcolor, newcolor; if (_plotter->drawstate->pen_type != 0) /* have a pen to draw with */ { /* set pen color as foreground color in GC used for drawing (but first, check whether we can avoid a function call) */ newcolor = _plotter->drawstate->fgcolor; oldcolor = _plotter->drawstate->x_current_fgcolor; /* as stored in gc */ if (newcolor.red != oldcolor.red || newcolor.green != oldcolor.green || newcolor.blue != oldcolor.blue || ! _plotter->drawstate->x_gc_fgcolor_status) _pl_x_set_pen_color (S___(_plotter)); xx = XD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y); yy = YD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y); ix = IROUND(xx); iy = IROUND(yy); if (_plotter->x_double_buffering != X_DBL_BUF_NONE) /* double buffering, have a `x_drawable3' to draw into */ XDrawPoint (_plotter->x_dpy, _plotter->x_drawable3, _plotter->drawstate->x_gc_fg, ix, iy); else /* not double buffering, have no `x_drawable3' */ { if (_plotter->x_drawable1) XDrawPoint (_plotter->x_dpy, _plotter->x_drawable1, _plotter->drawstate->x_gc_fg, ix, iy); if (_plotter->x_drawable2) XDrawPoint (_plotter->x_dpy, _plotter->x_drawable2, _plotter->drawstate->x_gc_fg, ix, iy); } } /* maybe flush X output buffer and handle X events (a no-op for XDrawablePlotters, which is overridden for XPlotters) */ if (_plotter->x_paint_pixel_count % X_POINT_FLUSH_PERIOD == 0) _maybe_handle_x_events (S___(_plotter)); _plotter->x_paint_pixel_count++; }
/** * Helper routine used by the other _mesa_PixelMap() functions. */ static void store_pixelmap(struct gl_context *ctx, GLenum map, GLsizei mapsize, const GLfloat *values) { GLint i; struct gl_pixelmap *pm = get_pixelmap(ctx, map); if (!pm) { _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)"); return; } switch (map) { case GL_PIXEL_MAP_S_TO_S: /* special case */ ctx->PixelMaps.StoS.Size = mapsize; for (i = 0; i < mapsize; i++) { ctx->PixelMaps.StoS.Map[i] = (GLfloat)IROUND(values[i]); } break; case GL_PIXEL_MAP_I_TO_I: /* special case */ ctx->PixelMaps.ItoI.Size = mapsize; for (i = 0; i < mapsize; i++) { ctx->PixelMaps.ItoI.Map[i] = values[i]; } break; default: /* general case */ pm->Size = mapsize; for (i = 0; i < mapsize; i++) { GLfloat val = CLAMP(values[i], 0.0F, 1.0F); pm->Map[i] = val; } } }
void _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLenum type ) { GET_CURRENT_CONTEXT(ctx); GLint destx, desty; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)" ); return; } if (ctx->NewState) { _mesa_update_state(ctx); } if (ctx->RenderMode==GL_RENDER) { /* Destination of copy: */ if (!ctx->Current.RasterPosValid) { return; } /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ destx = IROUND(ctx->Current.RasterPos[0]); desty = IROUND(ctx->Current.RasterPos[1]); ctx->OcclusionResult = GL_TRUE; ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type ); } else if (ctx->RenderMode == GL_FEEDBACK) { if (ctx->Current.RasterPosValid) { FLUSH_CURRENT(ctx, 0); FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterIndex, ctx->Current.RasterTexCoord ); } } else if (ctx->RenderMode == GL_SELECT) { _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] ); } }
/* * Execute glDrawPixels */ void _mesa_DrawPixels( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" ); return; } if (ctx->RenderMode==GL_RENDER) { GLint x, y; if (!pixels || !ctx->Current.RasterPosValid) { return; } if (ctx->NewState) { _mesa_update_state(ctx); } /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ x = IROUND(ctx->Current.RasterPos[0]); y = IROUND(ctx->Current.RasterPos[1]); ctx->OcclusionResult = GL_TRUE; ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type, &ctx->Unpack, pixels); } else if (ctx->RenderMode==GL_FEEDBACK) { if (ctx->Current.RasterPosValid) { FLUSH_CURRENT(ctx, 0); FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterIndex, ctx->Current.RasterTexCoord ); } } else if (ctx->RenderMode==GL_SELECT) { if (ctx->Current.RasterPosValid) { _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] ); } } }
/** * Run fragment program on the pixels in span from 'start' to 'end' - 1. */ static void run_program(GLcontext *ctx, SWspan *span, GLuint start, GLuint end) { SWcontext *swrast = SWRAST_CONTEXT(ctx); const struct gl_fragment_program *program = ctx->FragmentProgram._Current; const GLbitfield outputsWritten = program->Base.OutputsWritten; struct gl_program_machine *machine = &swrast->FragProgMachine; GLuint i; for (i = start; i < end; i++) { if (span->array->mask[i]) { init_machine(ctx, machine, program, span, i); if (_mesa_execute_program(ctx, &program->Base, machine)) { /* Store result color */ if (outputsWritten & (1 << FRAG_RESULT_COLR)) { COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0][i], machine->Outputs[FRAG_RESULT_COLR]); } else { /* Multiple drawbuffers / render targets * Note that colors beyond 0 and 1 will overwrite other * attributes, such as FOGC, TEX0, TEX1, etc. That's OK. */ GLuint output; for (output = 0; output < swrast->_NumColorOutputs; output++) { if (outputsWritten & (1 << (FRAG_RESULT_DATA0 + output))) { COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0+output][i], machine->Outputs[FRAG_RESULT_DATA0 + output]); } } } /* Store result depth/z */ if (outputsWritten & (1 << FRAG_RESULT_DEPR)) { const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPR][2]; if (depth <= 0.0) span->array->z[i] = 0; else if (depth >= 1.0) span->array->z[i] = ctx->DrawBuffer->_DepthMax; else span->array->z[i] = IROUND(depth * ctx->DrawBuffer->_DepthMaxF); } } else { /* killed fragment */ span->array->mask[i] = GL_FALSE; span->writeAll = GL_FALSE; } } } }
bool _pl_f_end_page (S___(Plotter *_plotter)) { int i; const char *units; plOutbuf *fig_header; /* prepare Fig header, write it to a plOutbuf */ fig_header = _new_outbuf (); units = (_plotter->data->page_data->metric ? "Metric" : "Inches"); sprintf (fig_header->point, "#FIG 3.2\n%s\n%s\n%s\n%s\n%.2f\n%s\n%d\n%d %d\n", "Portrait", /* portrait mode, not landscape */ "Flush Left", /* justification */ units, /* "Metric" or "Inches" */ _plotter->data->page_data->fig_name, /* paper size */ 100.00, /* export and print magnification */ "Single", /* "Single" or "Multiple" pages */ -2, /* color number for transparent color */ IROUND(FIG_UNITS_PER_INCH), /* Fig units per inch */ 2 /* origin in lower left corner (ignored) */ ); _update_buffer (fig_header); /* output user-defined colors if any */ for (i = 0; i < _plotter->fig_num_usercolors; i++) { sprintf (fig_header->point, "#COLOR\n%d %d #%06lx\n", 0, /* color pseudo-object */ FIG_USER_COLOR_MIN + i, /* color num, in xfig's range */ _plotter->fig_usercolors[i] /* 24-bit RGB value */ ); _update_buffer (fig_header); } /* place header in the plOutbuf for the page */ _plotter->data->page->header = fig_header; return true; }
static struct opengl_sc_bounding_box_t *opengl_sc_bounding_box_create(struct opengl_pa_triangle_t *triangle) { struct opengl_sc_bounding_box_t *bbox; float xmin; float xmax; float ymin; float ymax; float span; int snapMask; int s; int k; /* Allocate */ bbox = xcalloc(1, sizeof(struct opengl_sc_bounding_box_t)); /* Find the length of the span */ xmin = MIN(triangle->vtx0->pos[X_COMP], MIN(triangle->vtx1->pos[X_COMP], triangle->vtx2->pos[X_COMP])); xmax = MAX(triangle->vtx0->pos[X_COMP], MAX(triangle->vtx1->pos[X_COMP], triangle->vtx2->pos[X_COMP])); ymin = MIN(triangle->vtx0->pos[Y_COMP], MIN(triangle->vtx1->pos[Y_COMP], triangle->vtx2->pos[Y_COMP])); ymax = MAX(triangle->vtx0->pos[Y_COMP], MAX(triangle->vtx1->pos[Y_COMP], triangle->vtx2->pos[Y_COMP])); span = MAX(xmax - xmin, ymax - ymin); s = IROUND(span); /* Calculate bounding box size */ k = 0; do { k++; } while (s > (2<<k)); /* Snapping to nearest subpixel grid */ snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); bbox->x0 = FixedToInt(FloatToFixed(xmin - 0.5F) & snapMask); bbox->y0 = FixedToInt(FloatToFixed(ymin - 0.5F) & snapMask); bbox->size = 2<<k; /* Return */ return bbox; }
void _pl_h_paint_path (S___(Plotter *_plotter)) { if (_plotter->drawstate->pen_type == 0 && _plotter->drawstate->fill_type == 0) /* nothing to draw */ return; switch ((int)_plotter->drawstate->path->type) { case (int)PATH_SEGMENT_LIST: { plIntPathSegment *xarray; plPoint p0, pp1, pc, savedpoint; bool closed, use_polygon_buffer; double last_x, last_y; int i, polyline_len; bool identical_user_coordinates = true; /* sanity checks */ if (_plotter->drawstate->path->num_segments == 0)/* nothing to do */ break; if (_plotter->drawstate->path->num_segments == 1) /* shouldn't happen*/ break; if ((_plotter->drawstate->path->num_segments >= 3)/*check for closure*/ && (_plotter->drawstate->path->segments[_plotter->drawstate->path->num_segments - 1].p.x == _plotter->drawstate->path->segments[0].p.x) && (_plotter->drawstate->path->segments[_plotter->drawstate->path->num_segments - 1].p.y == _plotter->drawstate->path->segments[0].p.y)) closed = true; else closed = false; /* 2-point ones should be open */ /* convert vertices to integer device coordinates, removing runs */ /* array for points, with positions expressed in integer device coors*/ xarray = (plIntPathSegment *)_pl_xmalloc (_plotter->drawstate->path->num_segments * sizeof(plIntPathSegment)); /* add first point of path to xarray[] (type field is a moveto) */ xarray[0].p.x = IROUND(XD(_plotter->drawstate->path->segments[0].p.x, _plotter->drawstate->path->segments[0].p.y)); xarray[0].p.y = IROUND(YD(_plotter->drawstate->path->segments[0].p.x, _plotter->drawstate->path->segments[0].p.y)); polyline_len = 1; /* save user coors of last point added to xarray[] */ last_x = _plotter->drawstate->path->segments[0].p.x; last_y = _plotter->drawstate->path->segments[0].p.y; for (i = 1; i < _plotter->drawstate->path->num_segments; i++) { plPathSegment datapoint; double xuser, yuser, xdev, ydev; int device_x, device_y; datapoint = _plotter->drawstate->path->segments[i]; xuser = datapoint.p.x; yuser = datapoint.p.y; if (xuser != last_x || yuser != last_y) /* in user space, not all points are the same */ identical_user_coordinates = false; xdev = XD(xuser, yuser); ydev = YD(xuser, yuser); device_x = IROUND(xdev); device_y = IROUND(ydev); if (device_x != xarray[polyline_len-1].p.x || device_y != xarray[polyline_len-1].p.y) /* integer device coor(s) changed, so stash point (incl. type field) */ { plPathSegmentType element_type; int device_xc, device_yc; xarray[polyline_len].p.x = device_x; xarray[polyline_len].p.y = device_y; element_type = datapoint.type; xarray[polyline_len].type = element_type; if (element_type == S_ARC) /* an arc element, so compute center, subtended angle too */ { double angle; device_xc = IROUND(XD(datapoint.pc.x, datapoint.pc.y)); device_yc = IROUND(YD(datapoint.pc.x, datapoint.pc.y)); xarray[polyline_len].pc.x = device_xc; xarray[polyline_len].pc.y = device_yc; p0.x = last_x; p0.y = last_y; pp1 = datapoint.p; pc = datapoint.pc; angle = _angle_of_arc (p0, pp1, pc); /* if user coors -> device coors includes a reflection, flip sign */ if (!_plotter->drawstate->transform.nonreflection) angle = -angle; xarray[polyline_len].angle = angle; } else if (element_type == S_CUBIC) /* a cubic Bezier element, so compute control points too */ { xarray[polyline_len].pc.x = IROUND(XD(datapoint.pc.x, datapoint.pc.y)); xarray[polyline_len].pc.y = IROUND(YD(datapoint.pc.x, datapoint.pc.y)); xarray[polyline_len].pd.x = IROUND(XD(datapoint.pd.x, datapoint.pd.y)); xarray[polyline_len].pd.y = IROUND(YD(datapoint.pd.x, datapoint.pd.y)); } /* save user coors of last point added to xarray[] */ last_x = datapoint.p.x; last_y = datapoint.p.y; polyline_len++; } } /* Check first for special subcase: all user-space juncture points in the polyline were mapped to a single integer HP-GL pseudo-pixel. If (1) they weren't all the same to begin with, or (2) they were all the same to begin with and the cap mode is "round", then draw as a filled circle, of diameter equal to the line width; otherwise draw nothing. */ if (_plotter->drawstate->path->num_segments > 1 && polyline_len == 1) /* all points mapped to a single integer pseudo-pixel */ { if (identical_user_coordinates == false || _plotter->drawstate->cap_type == PL_CAP_ROUND) { double r = 0.5 * _plotter->drawstate->line_width; double device_frame_radius; /* draw single filled circle, using HP-GL's native circle-drawing facility */ /* move to center of circle */ savedpoint = _plotter->drawstate->pos; _plotter->drawstate->pos = _plotter->drawstate->path->segments[0].p; _pl_h_set_position (S___(_plotter)); _plotter->drawstate->pos = savedpoint; /* set fill color to pen color, arrange to do filling; sync attributes too, incl. pen width */ { /* emit HP-GL directives; select a fill color that's actually the pen color */ _pl_h_set_fill_color (R___(_plotter) true); _pl_h_set_attributes (S___(_plotter)); } /* compute radius in device frame */ device_frame_radius = sqrt(XDV(r,0)*XDV(r,0)+YDV(r,0)*YDV(r,0)); /* Syncing the fill color may have set the _plotter->hpgl_bad_pen flag (e.g. if optimal pen is #0 [white] and we're not allowed to use pen #0 to draw with). So we test _plotter->hpgl_bad_pen before using the pen. */ if (_plotter->hpgl_bad_pen == false) /* fill the circle (360 degree wedge) */ { sprintf (_plotter->data->page->point, "WG%d,0,360;", IROUND(device_frame_radius)); _update_buffer (_plotter->data->page); } /* KLUDGE: in pre-HP-GL/2, our `set_fill_color' function may alter the line type, since it may request *solid* crosshatching; so reset the line type */ if (_plotter->hpgl_version < 2) _pl_h_set_attributes (S___(_plotter)); } /* free our temporary array and depart */ free (xarray); break; } /* At this point, we know we have a nondegenerate path in our pseudo-integer device space. */ /* will draw vectors (or arcs) into polygon buffer if appropriate */ use_polygon_buffer = (_plotter->hpgl_version == 2 || (_plotter->hpgl_version == 1 /* i.e. "1.5" */ && (polyline_len > 2 || _plotter->drawstate->fill_type)) ? true : false); /* Sync pen color. This is needed here only if HPGL_VERSION is 1, but we always do it here so that HP-GL/2 output that draws a polyline, if sent erroneously to a generic HP-GL device, will yield a polyline in the correct color, so long as the color isn't white. */ _pl_h_set_pen_color (R___(_plotter) HPGL_OBJECT_PATH); /* set_pen_color() sets the advisory bad_pen flag if white pen (pen #0) would have been selected, and we can't use pen #0 to draw with. Such a situation isn't fatal if HPGL_VERSION is "1.5" or "2", since we may be filling the polyline with a nonwhite color, as well as using a white pen to draw it. But if HPGL_VERSION is "1", we don't fill polylines, so we might as well punt right now. */ if (_plotter->hpgl_bad_pen && _plotter->hpgl_version == 1) { /* free integer storage buffer and depart */ free (xarray); break; } /* sync attributes, incl. pen width if possible; move pen to p0 */ _pl_h_set_attributes (S___(_plotter)); savedpoint = _plotter->drawstate->pos; _plotter->drawstate->pos = _plotter->drawstate->path->segments[0].p; _pl_h_set_position (S___(_plotter)); _plotter->drawstate->pos = savedpoint; if (use_polygon_buffer) /* have a polygon buffer, and can use it to fill polyline */ { /* enter polygon mode */ strcpy (_plotter->data->page->point, "PM0;"); _update_buffer (_plotter->data->page); } if (use_polygon_buffer || _plotter->drawstate->pen_type) /* either (1) we'll be drawing into a polygon buffer, and will be using it for at least one of (a) filling and (b) edging, or (2) we won't be drawing into a polygon buffer, so we won't be filling, but we'll be edging (because pen_type isn't zero) */ { /* ensure that pen is down for drawing */ if (_plotter->hpgl_pendown == false) { strcpy (_plotter->data->page->point, "PD;"); _update_buffer (_plotter->data->page); _plotter->hpgl_pendown = true; } /* loop through points in xarray[], emitting HP-GL instructions */ i = 1; while (i < polyline_len) { switch ((int)xarray[i].type) { case (int)S_LINE: /* emit one or more pen advances */ strcpy (_plotter->data->page->point, "PA"); _update_buffer (_plotter->data->page); sprintf (_plotter->data->page->point, "%d,%d", xarray[i].p.x, xarray[i].p.y); _update_buffer (_plotter->data->page); i++; while (i < polyline_len && xarray[i].type == S_LINE) { sprintf (_plotter->data->page->point, ",%d,%d", xarray[i].p.x, xarray[i].p.y); _update_buffer (_plotter->data->page); i++; } sprintf (_plotter->data->page->point, ";"); _update_buffer (_plotter->data->page); break; case (int)S_CUBIC: /* emit one or more cubic Bezier segments */ strcpy (_plotter->data->page->point, "BZ"); _update_buffer (_plotter->data->page); sprintf (_plotter->data->page->point, "%d,%d,%d,%d,%d,%d", xarray[i].pc.x, xarray[i].pc.y, xarray[i].pd.x, xarray[i].pd.y, xarray[i].p.x, xarray[i].p.y); _update_buffer (_plotter->data->page); i++; while (i < polyline_len && xarray[i].type == S_CUBIC) { sprintf (_plotter->data->page->point, ",%d,%d,%d,%d,%d,%d", xarray[i].pc.x, xarray[i].pc.y, xarray[i].pd.x, xarray[i].pd.y, xarray[i].p.x, xarray[i].p.y); _update_buffer (_plotter->data->page); i++; } sprintf (_plotter->data->page->point, ";"); _update_buffer (_plotter->data->page); break; case (int)S_ARC: { double degrees; int int_degrees; /* emit an arc, using integer sweep angle if possible */ degrees = 180.0 * xarray[i].angle / M_PI; int_degrees = IROUND (degrees); if (_plotter->hpgl_version > 0) /* HPGL_VERSION = 1.5 or 2 */ { if (degrees == (double)int_degrees) sprintf (_plotter->data->page->point, "AA%d,%d,%d;", xarray[i].pc.x, xarray[i].pc.y, int_degrees); else sprintf (_plotter->data->page->point, "AA%d,%d,%.3f;", xarray[i].pc.x, xarray[i].pc.y, degrees); } else /* HPGL_VERSION = 1, i.e. generic HP-GL */ /* note: generic HP-GL can only handle integer sweep angles */ sprintf (_plotter->data->page->point, "AA%d,%d,%d;", xarray[i].pc.x, xarray[i].pc.y, int_degrees); _update_buffer (_plotter->data->page); i++; } break; default: /* shouldn't happen: unknown type for path segment, ignore */ i++; break; } } } if (use_polygon_buffer) /* using polygon mode; will now employ polygon buffer to do filling (possibly) and edging */ { if (!closed) /* polyline is open, so lift pen and exit polygon mode */ { strcpy (_plotter->data->page->point, "PU;"); _update_buffer (_plotter->data->page); _plotter->hpgl_pendown = false; strcpy (_plotter->data->page->point, "PM2;"); _update_buffer (_plotter->data->page); } else /* polyline is closed, so exit polygon mode and then lift pen */ { strcpy (_plotter->data->page->point, "PM2;"); _update_buffer (_plotter->data->page); strcpy (_plotter->data->page->point, "PU;"); _update_buffer (_plotter->data->page); _plotter->hpgl_pendown = false; } if (_plotter->drawstate->fill_type) /* polyline should be filled */ { /* Sync fill color. This may set the _plotter->hpgl_bad_pen flag (if optimal pen is #0 [white] and we're not allowed to use pen #0 to draw with). So we test _plotter->hpgl_bad_pen before using the pen to fill with. */ _pl_h_set_fill_color (R___(_plotter) false); if (_plotter->hpgl_bad_pen == false) /* fill polyline, specifying nonzero winding rule if necessary */ { switch (_plotter->drawstate->fill_rule_type) { case PL_FILL_ODD_WINDING: default: strcpy (_plotter->data->page->point, "FP;"); break; case PL_FILL_NONZERO_WINDING: if (_plotter->hpgl_version == 2) strcpy (_plotter->data->page->point, "FP1;"); else /* pre-HP-GL/2 doesn't support nonzero rule */ strcpy (_plotter->data->page->point, "FP;"); break; } _update_buffer (_plotter->data->page); } /* KLUDGE: in pre-HP-GL/2, our `set_fill_color' function may alter the line type, since it may request *solid* crosshatching; so reset the line type */ if (_plotter->hpgl_version < 2) _pl_h_set_attributes (S___(_plotter)); } if (_plotter->drawstate->pen_type) /* polyline should be edged */ { /* Sync pen color. This may set the _plotter->hpgl_bad_pen flag (if optimal pen is #0 and we're not allowed to use pen #0 to draw with). So we test _plotter->hpgl_bad_pen before using the pen. */ _pl_h_set_pen_color (R___(_plotter) HPGL_OBJECT_PATH); if (_plotter->hpgl_bad_pen == false) /* select appropriate pen for edging, and edge the polyline */ { _pl_h_set_pen_color (R___(_plotter) HPGL_OBJECT_PATH); strcpy (_plotter->data->page->point, "EP;"); _update_buffer (_plotter->data->page); } } } /* We know where the pen now is: if we used a polygon buffer, then _plotter->hpgl_pos is now xarray[0].p. If we didn't (as would be the case if we're outputting generic HP-GL), then _plotter->hpgl_pos is now xarray[polyline_len - 1].p. Unfortunately we can't simply update _plotter->hpgl_pos, because we want the generated HP-GL[/2] code to work properly on both HP-GL and HP-GL/2 devices. So we punt. */ _plotter->hpgl_position_is_unknown = true; /* free integer storage buffer and depart */ free (xarray); } break; case (int)PATH_BOX: { plPoint p0, p1, savedpoint; p0 = _plotter->drawstate->path->p0; p1 = _plotter->drawstate->path->p1; /* sync line attributes, incl. pen width */ _pl_h_set_attributes (S___(_plotter)); /* move HP-GL pen to first vertex */ savedpoint = _plotter->drawstate->pos; _plotter->drawstate->pos = p0; _pl_h_set_position (S___(_plotter)); _plotter->drawstate->pos = savedpoint; if (_plotter->drawstate->fill_type) /* rectangle should be filled */ { /* Sync fill color. This may set the _plotter->hpgl_bad_pen flag (e.g. if optimal pen is #0 [white] and we're not allowed to use pen #0 to draw with). So we test _plotter->hpgl_bad_pen before using the pen. */ _pl_h_set_fill_color (R___(_plotter) false); if (_plotter->hpgl_bad_pen == false) /* fill the rectangle */ { sprintf (_plotter->data->page->point, "RA%d,%d;", IROUND(XD(p1.x,p1.y)), IROUND(YD(p1.x,p1.y))); _update_buffer (_plotter->data->page); } /* KLUDGE: in pre-HP-GL/2, our `set_fill_color' function may alter the line type, since it may request *solid* crosshatching; so reset it */ if (_plotter->hpgl_version < 2) _pl_h_set_attributes (S___(_plotter)); } if (_plotter->drawstate->pen_type) /* rectangle should be edged */ { /* Sync pen color. This may set the _plotter->hpgl_bad_pen flag (e.g. if optimal pen is #0 [white] and we're not allowed to use pen #0 to draw with). So we test _plotter->hpgl_bad_pen before using the pen. */ _pl_h_set_pen_color (R___(_plotter) HPGL_OBJECT_PATH); if (_plotter->hpgl_bad_pen == false) /* edge the rectangle */ { sprintf (_plotter->data->page->point, "EA%d,%d;", IROUND(XD(p1.x,p1.y)), IROUND(YD(p1.x,p1.y))); _update_buffer (_plotter->data->page); } } } break; case (int)PATH_CIRCLE: { plPoint pc, savedpoint; double r = _plotter->drawstate->path->radius; double radius = sqrt(XDV(r,0)*XDV(r,0)+YDV(r,0)*YDV(r,0)); pc = _plotter->drawstate->path->pc; /* sync attributes, incl. pen width; move to center of circle */ _pl_h_set_attributes (S___(_plotter)); savedpoint = _plotter->drawstate->pos; _plotter->drawstate->pos = pc; _pl_h_set_position (S___(_plotter)); _plotter->drawstate->pos = savedpoint; if (_plotter->drawstate->fill_type) /* circle should be filled */ { /* Sync fill color. This may set the _plotter->hpgl_bad_pen flag (e.g. if optimal pen is #0 [white] and we're not allowed to use pen #0 to draw with). So we test _plotter->hpgl_bad_pen before using the pen. */ _pl_h_set_fill_color (R___(_plotter) false); if (_plotter->hpgl_bad_pen == false) /* fill the circle (360 degree wedge) */ { sprintf (_plotter->data->page->point, "WG%d,0,360;", IROUND(radius)); _update_buffer (_plotter->data->page); } /* KLUDGE: in pre-HP-GL/2, our `set_fill_color' function may alter the line type, since it may request *solid* crosshatching; so reset it */ if (_plotter->hpgl_version < 2) _pl_h_set_attributes (S___(_plotter)); } if (_plotter->drawstate->pen_type) /* circle should be edged */ { /* Sync pen color. This may set the _plotter->hpgl_bad_pen flag (e.g. if optimal pen is #0 [white] and we're not allowed to use pen #0 to draw with). So we test _plotter->hpgl_bad_pen before using the pen. */ _pl_h_set_pen_color (R___(_plotter) HPGL_OBJECT_PATH); if (_plotter->hpgl_bad_pen == false) /* do the edging */ { sprintf (_plotter->data->page->point, "CI%d;", IROUND(radius)); _update_buffer (_plotter->data->page); } } } break; default: /* unrecognized path type, shouldn't happen */ break; } }
/* * Execute glDrawPixels */ static void GLAPIENTRY _mesa_DrawPixels( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) { GLenum err; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glDrawPixels(%d, %d, %s, %s, %p) // to %s at %d, %d\n", width, height, _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type), pixels, _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]), IROUND(ctx->Current.RasterPos[0]), IROUND(ctx->Current.RasterPos[1])); if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0)" ); return; } /* We're not using the current vertex program, and the driver may install * its own. Note: this may dirty some state. */ _mesa_set_vp_override(ctx, GL_TRUE); /* Note: this call does state validation */ if (!_mesa_valid_to_render(ctx, "glDrawPixels")) { goto end; /* the error code was recorded */ } /* GL 3.0 introduced a new restriction on glDrawPixels() over what was in * GL_EXT_texture_integer. From section 3.7.4 ("Rasterization of Pixel * Rectangles) on page 151 of the GL 3.0 specification: * * "If format contains integer components, as shown in table 3.6, an * INVALID OPERATION error is generated." * * Since DrawPixels rendering would be merely undefined if not an error (due * to a lack of defined mapping from integer data to gl_Color fragment shader * input), NVIDIA's implementation also just returns this error despite * exposing GL_EXT_texture_integer, just return an error regardless. */ if (_mesa_is_enum_format_integer(format)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(integer format)"); goto end; } err = _mesa_error_check_format_and_type(ctx, format, type); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glDrawPixels(invalid format %s and/or type %s)", _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); goto end; } /* do special format-related checks */ switch (format) { case GL_STENCIL_INDEX: case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL_EXT: /* these buffers must exist */ if (!_mesa_dest_buffer_exists(ctx, format)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(missing deest buffer)"); goto end; } break; case GL_COLOR_INDEX: 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)"); goto end; } break; default: /* for color formats it's not an error if the destination color * buffer doesn't exist. */ break; } if (ctx->RasterDiscard) { goto end; } if (!ctx->Current.RasterPosValid) { goto end; /* no-op, not an error */ } if (ctx->RenderMode == GL_RENDER) { if (width > 0 && height > 0) { /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ GLint x = IROUND(ctx->Current.RasterPos[0]); GLint y = IROUND(ctx->Current.RasterPos[1]); if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* unpack from PBO */ if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, format, type, INT_MAX, pixels)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(invalid PBO access)"); goto end; } if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(PBO is mapped)"); goto end; } } ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type, &ctx->Unpack, pixels); } } else if (ctx->RenderMode == GL_FEEDBACK) { /* Feedback the current raster pos info */ FLUSH_CURRENT( ctx, 0 ); _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } end: _mesa_set_vp_override(ctx, GL_FALSE); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
static void GLAPIENTRY _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLenum type ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glCopyPixels(%d, %d, %d, %d, %s) // from %s to %s at %d, %d\n", srcx, srcy, width, height, _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(ctx->ReadBuffer->ColorReadBuffer), _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]), IROUND(ctx->Current.RasterPos[0]), IROUND(ctx->Current.RasterPos[1])); if (width < 0 || height < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)"); return; } /* Note: more detailed 'type' checking is done by the * _mesa_source/dest_buffer_exists() calls below. That's where we * check if the stencil buffer exists, etc. */ if (type != GL_COLOR && type != GL_DEPTH && type != GL_STENCIL && type != GL_DEPTH_STENCIL) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)", _mesa_lookup_enum_by_nr(type)); return; } /* We're not using the current vertex program, and the driver may install * it's own. Note: this may dirty some state. */ _mesa_set_vp_override(ctx, GL_TRUE); /* Note: this call does state validation */ if (!_mesa_valid_to_render(ctx, "glCopyPixels")) { goto end; /* the error code was recorded */ } /* Check read buffer's status (draw buffer was already checked) */ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glCopyPixels(incomplete framebuffer)" ); goto end; } if (_mesa_is_user_fbo(ctx->ReadBuffer) && ctx->ReadBuffer->Visual.samples > 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyPixels(multisample FBO)"); goto end; } if (!_mesa_source_buffer_exists(ctx, type) || !_mesa_dest_buffer_exists(ctx, type)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyPixels(missing source or dest buffer)"); goto end; } if (ctx->RasterDiscard) { goto end; } if (!ctx->Current.RasterPosValid || width == 0 || height == 0) { goto end; /* no-op, not an error */ } if (ctx->RenderMode == GL_RENDER) { /* Round to satisfy conformance tests (matches SGI's OpenGL) */ if (width > 0 && height > 0) { GLint destx = IROUND(ctx->Current.RasterPos[0]); GLint desty = IROUND(ctx->Current.RasterPos[1]); ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type ); } } else if (ctx->RenderMode == GL_FEEDBACK) { FLUSH_CURRENT( ctx, 0 ); _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } end: _mesa_set_vp_override(ctx, GL_FALSE); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
/* * Try to do a fast and simple RGB(a) glDrawPixels. * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead */ static GLboolean fast_draw_pixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) { SWcontext *swrast = SWRAST_CONTEXT(ctx); struct sw_span span; INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA); if (!ctx->Current.RasterPosValid) { return GL_TRUE; /* no-op */ } if (ctx->Depth.Test) _swrast_span_default_z(ctx, &span); if (ctx->Fog.Enabled) _swrast_span_default_fog(ctx, &span); if (ctx->Texture._EnabledCoordUnits) _swrast_span_default_texcoords(ctx, &span); if ((SWRAST_CONTEXT(ctx)->_RasterMask & ~CLIP_BIT) == 0 && ctx->Texture._EnabledCoordUnits == 0 && unpack->Alignment == 1 && !unpack->SwapBytes && !unpack->LsbFirst) { GLint destX = x; GLint destY = y; GLint drawWidth = width; /* actual width drawn */ GLint drawHeight = height; /* actual height drawn */ GLint skipPixels = unpack->SkipPixels; GLint skipRows = unpack->SkipRows; GLint rowLength; GLint zoomY0 = 0; if (unpack->RowLength > 0) rowLength = unpack->RowLength; else rowLength = width; /* If we're not using pixel zoom then do all clipping calculations * now. Otherwise, we'll let the _swrast_write_zoomed_*_span() functions * handle the clipping. */ if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { /* horizontal clipping */ if (destX < ctx->DrawBuffer->_Xmin) { skipPixels += (ctx->DrawBuffer->_Xmin - destX); drawWidth -= (ctx->DrawBuffer->_Xmin - destX); destX = ctx->DrawBuffer->_Xmin; } if (destX + drawWidth > ctx->DrawBuffer->_Xmax) drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax); if (drawWidth <= 0) return GL_TRUE; /* vertical clipping */ if (destY < ctx->DrawBuffer->_Ymin) { skipRows += (ctx->DrawBuffer->_Ymin - destY); drawHeight -= (ctx->DrawBuffer->_Ymin - destY); destY = ctx->DrawBuffer->_Ymin; } if (destY + drawHeight > ctx->DrawBuffer->_Ymax) drawHeight -= (destY + drawHeight - ctx->DrawBuffer->_Ymax); if (drawHeight <= 0) return GL_TRUE; } else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { /* upside-down image */ /* horizontal clipping */ if (destX < ctx->DrawBuffer->_Xmin) { skipPixels += (ctx->DrawBuffer->_Xmin - destX); drawWidth -= (ctx->DrawBuffer->_Xmin - destX); destX = ctx->DrawBuffer->_Xmin; } if (destX + drawWidth > ctx->DrawBuffer->_Xmax) drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax); if (drawWidth <= 0) return GL_TRUE; /* vertical clipping */ if (destY > ctx->DrawBuffer->_Ymax) { skipRows += (destY - ctx->DrawBuffer->_Ymax); drawHeight -= (destY - ctx->DrawBuffer->_Ymax); destY = ctx->DrawBuffer->_Ymax; } if (destY - drawHeight < ctx->DrawBuffer->_Ymin) drawHeight -= (ctx->DrawBuffer->_Ymin - (destY - drawHeight)); if (drawHeight <= 0) return GL_TRUE; } else { if (drawWidth > MAX_WIDTH) return GL_FALSE; /* fall back to general case path */ /* save Y value of first row */ zoomY0 = IROUND(ctx->Current.RasterPos[1]); } /* * Ready to draw! * The window region at (destX, destY) of size (drawWidth, drawHeight) * will be written to. * We'll take pixel data from buffer pointed to by "pixels" but we'll * skip "skipRows" rows and skip "skipPixels" pixels/row. */ if (format == GL_RGBA && type == CHAN_TYPE && ctx->_ImageTransferState==0) { if (ctx->Visual.rgbMode) { GLchan *src = (GLchan *) pixels + (skipRows * rowLength + skipPixels) * 4; if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { /* no zooming */ GLint row; for (row=0; row<drawHeight; row++) { (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, (CONST GLchan (*)[4]) src, NULL); src += rowLength * 4; destY++; } } else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { /* upside-down */ GLint row; for (row=0; row<drawHeight; row++) { destY--; (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, (CONST GLchan (*)[4]) src, NULL); src += rowLength * 4; } } else { /* with zooming */ GLint row; for (row=0; row<drawHeight; row++) { span.x = destX; span.y = destY; span.end = drawWidth; _swrast_write_zoomed_rgba_span(ctx, &span, (CONST GLchan (*)[4]) src, zoomY0, 0); src += rowLength * 4; destY++; } } } return GL_TRUE; } else if (format == GL_RGB && type == CHAN_TYPE && ctx->_ImageTransferState == 0) { if (ctx->Visual.rgbMode) { GLchan *src = (GLchan *) pixels + (skipRows * rowLength + skipPixels) * 3; if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { GLint row; for (row=0; row<drawHeight; row++) { (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, (CONST GLchan (*)[3]) src, NULL); src += rowLength * 3; destY++; } } else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { /* upside-down */ GLint row; for (row=0; row<drawHeight; row++) { destY--; (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, (CONST GLchan (*)[3]) src, NULL); src += rowLength * 3; } } else { /* with zooming */ GLint row; for (row=0; row<drawHeight; row++) { span.x = destX; span.y = destY; span.end = drawWidth; _swrast_write_zoomed_rgb_span(ctx, &span, (CONST GLchan (*)[3]) src, zoomY0, 0); src += rowLength * 3; destY++; } } } return GL_TRUE; } else if (format == GL_LUMINANCE && type == CHAN_TYPE && ctx->_ImageTransferState==0) { if (ctx->Visual.rgbMode) { GLchan *src = (GLchan *) pixels + (skipRows * rowLength + skipPixels); if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { /* no zooming */ GLint row; ASSERT(drawWidth <= MAX_WIDTH); for (row=0; row<drawHeight; row++) { GLint i; for (i=0;i<drawWidth;i++) { span.array->rgb[i][0] = src[i]; span.array->rgb[i][1] = src[i]; span.array->rgb[i][2] = src[i]; } (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, (CONST GLchan (*)[3]) span.array->rgb, NULL); src += rowLength; destY++; } } else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { /* upside-down */ GLint row; ASSERT(drawWidth <= MAX_WIDTH); for (row=0; row<drawHeight; row++) { GLint i; for (i=0;i<drawWidth;i++) { span.array->rgb[i][0] = src[i]; span.array->rgb[i][1] = src[i]; span.array->rgb[i][2] = src[i]; } destY--; (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY, (CONST GLchan (*)[3]) span.array->rgb, NULL); src += rowLength; } } else { /* with zooming */ GLint row; ASSERT(drawWidth <= MAX_WIDTH); for (row=0; row<drawHeight; row++) { GLint i; for (i=0;i<drawWidth;i++) { span.array->rgb[i][0] = src[i]; span.array->rgb[i][1] = src[i]; span.array->rgb[i][2] = src[i]; } span.x = destX; span.y = destY; span.end = drawWidth; _swrast_write_zoomed_rgb_span(ctx, &span, (CONST GLchan (*)[3]) span.array->rgb, zoomY0, 0); src += rowLength; destY++; } } } return GL_TRUE; } else if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE && ctx->_ImageTransferState == 0) { if (ctx->Visual.rgbMode) { GLchan *src = (GLchan *) pixels + (skipRows * rowLength + skipPixels)*2; if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { /* no zooming */ GLint row; ASSERT(drawWidth <= MAX_WIDTH); for (row=0; row<drawHeight; row++) { GLint i; GLchan *ptr = src; for (i=0;i<drawWidth;i++) { span.array->rgba[i][0] = *ptr; span.array->rgba[i][1] = *ptr; span.array->rgba[i][2] = *ptr++; span.array->rgba[i][3] = *ptr++; } (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, (CONST GLchan (*)[4]) span.array->rgba, NULL); src += rowLength*2; destY++; } } else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { /* upside-down */ GLint row; ASSERT(drawWidth <= MAX_WIDTH); for (row=0; row<drawHeight; row++) { GLint i; GLchan *ptr = src; for (i=0;i<drawWidth;i++) { span.array->rgba[i][0] = *ptr; span.array->rgba[i][1] = *ptr; span.array->rgba[i][2] = *ptr++; span.array->rgba[i][3] = *ptr++; } destY--; (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, (CONST GLchan (*)[4]) span.array->rgba, NULL); src += rowLength*2; } } else { /* with zooming */ GLint row; ASSERT(drawWidth <= MAX_WIDTH); for (row=0; row<drawHeight; row++) { GLchan *ptr = src; GLint i; for (i=0;i<drawWidth;i++) { span.array->rgba[i][0] = *ptr; span.array->rgba[i][1] = *ptr; span.array->rgba[i][2] = *ptr++; span.array->rgba[i][3] = *ptr++; } span.x = destX; span.y = destY; span.end = drawWidth; _swrast_write_zoomed_rgba_span(ctx, &span, (CONST GLchan (*)[4]) span.array->rgba, zoomY0, 0); src += rowLength*2; destY++; } } } return GL_TRUE; } else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) { GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels; if (ctx->Visual.rgbMode) { /* convert CI data to RGBA */ if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { /* no zooming */ GLint row; for (row=0; row<drawHeight; row++) { ASSERT(drawWidth <= MAX_WIDTH); _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba); (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, (const GLchan (*)[4]) span.array->rgba, NULL); src += rowLength; destY++; } return GL_TRUE; } else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) { /* upside-down */ GLint row; for (row=0; row<drawHeight; row++) { ASSERT(drawWidth <= MAX_WIDTH); _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba); destY--; (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY, (CONST GLchan (*)[4]) span.array->rgba, NULL); src += rowLength; } return GL_TRUE; } else { /* with zooming */ GLint row; for (row=0; row<drawHeight; row++) { ASSERT(drawWidth <= MAX_WIDTH); _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba); span.x = destX; span.y = destY; span.end = drawWidth; _swrast_write_zoomed_rgba_span(ctx, &span, (CONST GLchan (*)[4]) span.array->rgba, zoomY0, 0); src += rowLength; destY++; } return GL_TRUE; } } else if (ctx->_ImageTransferState==0) { /* write CI data to CI frame buffer */ GLint row; if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) { /* no zooming */ for (row=0; row<drawHeight; row++) { (*swrast->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY, src, NULL); src += rowLength; destY++; } return GL_TRUE; } else { /* with zooming */ return GL_FALSE; } } } else { /* can't handle this pixel format and/or data type here */ return GL_FALSE; } } /* can't do a simple draw, have to use slow path */ return GL_FALSE; }
void _pl_x_paint_path (S___(Plotter *_plotter)) { if (_plotter->drawstate->pen_type == 0 && _plotter->drawstate->fill_type == 0) /* nothing to draw */ return; switch ((int)_plotter->drawstate->path->type) { case (int)PATH_SEGMENT_LIST: { bool closed; /* not currently used */ int is_a_rectangle; int i, polyline_len; plPoint p0, p1, pc; XPoint *xarray, local_xarray[MAX_NUM_POINTS_ON_STACK]; bool heap_storage; double xu_last, yu_last; bool identical_user_coordinates; /* sanity checks */ if (_plotter->drawstate->path->num_segments == 0)/* nothing to do */ break; if (_plotter->drawstate->path->num_segments == 1) /*shouldn't happen */ break; if (_plotter->drawstate->path->num_segments == 2 && _plotter->drawstate->path->segments[1].type == S_ARC) /* segment buffer contains a single circular arc, not a polyline */ { p0 = _plotter->drawstate->path->segments[0].p; p1 = _plotter->drawstate->path->segments[1].p; pc = _plotter->drawstate->path->segments[1].pc; /* use native X rendering to draw the (transformed) circular arc */ _pl_x_draw_elliptic_arc (R___(_plotter) p0, p1, pc); break; } if (_plotter->drawstate->path->num_segments == 2 && _plotter->drawstate->path->segments[1].type == S_ELLARC) /* segment buffer contains a single elliptic arc, not a polyline */ { p0 = _plotter->drawstate->path->segments[0].p; p1 = _plotter->drawstate->path->segments[1].p; pc = _plotter->drawstate->path->segments[1].pc; /* use native X rendering to draw the (transformed) elliptic arc */ _pl_x_draw_elliptic_arc_2 (R___(_plotter) p0, p1, pc); break; } /* neither of above applied, so segment buffer contains a polyline, not an arc */ if ((_plotter->drawstate->path->num_segments >= 3)/*check for closure*/ && (_plotter->drawstate->path->segments[_plotter->drawstate->path->num_segments - 1].p.x == _plotter->drawstate->path->segments[0].p.x) && (_plotter->drawstate->path->segments[_plotter->drawstate->path->num_segments - 1].p.y == _plotter->drawstate->path->segments[0].p.y)) closed = true; else closed = false; /* 2-point ones should be open */ /* Check whether we `pre-drew' the polyline, i.e., drew every line segment in real time. (See the maybe_prepaint_segments() method further below, which is invoked to do that.) Our convention: we pre-draw only if pen width is zero, and line style is "solid". Also, we don't do it if we're drawing a polygonalized built-in object (i.e. a rectangle or ellipse). If we pre-drew, we don't do anything here unless there's filling to be done. If so, we'll fill the polyline and re-edge it. */ if ((_plotter->drawstate->pen_type != 0 /* pen is present */ && _plotter->drawstate->line_type == PL_L_SOLID && !_plotter->drawstate->dash_array_in_effect /* really solid */ && _plotter->drawstate->points_are_connected /* really, really */ && _plotter->drawstate->quantized_device_line_width == 0 && !_plotter->drawstate->path->primitive) /* not builtin object */ /* we pre-drew */ && _plotter->drawstate->fill_type == 0) /* there's no filling to be done, so we're out of here */ break; /* At this point we know that we didn't pre-draw, or we did, but the polyline was drawn unfilled and it'll need to be re-drawn as filled. */ /* prepare an array of XPoint structures (X11 uses short ints for these) */ if (_plotter->drawstate->path->num_segments <= MAX_NUM_POINTS_ON_STACK) /* store XPoints on stack, for speed */ { xarray = local_xarray; heap_storage = false; } else /* store XPoints in heap */ { xarray = (XPoint *)_pl_xmalloc (_plotter->drawstate->path->num_segments * sizeof(XPoint)); heap_storage = true; } /* convert vertices to device coordinates, removing runs; also keep track of whether or not all points in user space are the same */ polyline_len = 0; xu_last = 0.0; yu_last = 0.0; identical_user_coordinates = true; for (i = 0; i < _plotter->drawstate->path->num_segments; i++) { plPathSegment datapoint; double xu, yu, xd, yd; int device_x, device_y; datapoint = _plotter->drawstate->path->segments[i]; xu = datapoint.p.x; yu = datapoint.p.y; xd = XD(xu, yu); yd = YD(xu, yu); device_x = IROUND(xd); device_y = IROUND(yd); if (X_OOB_INT(device_x) || X_OOB_INT(device_y)) /* point position can't be represented using X11's 2-byte ints, so truncate the polyline right here */ { _plotter->warning (R___(_plotter) "truncating a polyline that extends too far for X11"); break; } if (i > 0 && (xu != xu_last || yu != yu_last)) /* in user space, not all points are the same */ identical_user_coordinates = false; if ((polyline_len == 0) || (device_x != xarray[polyline_len-1].x) || (device_y != xarray[polyline_len-1].y)) /* add point, in integer X coordinates, to the array */ { xarray[polyline_len].x = device_x; xarray[polyline_len].y = device_y; polyline_len++; if (polyline_len >= _plotter->x_max_polyline_len) /* polyline is getting too long for the X server to handle (we determined the maximum X request size when openpl() was invoked), so truncate it right here */ { _plotter->warning (R___(_plotter) "truncating a polyline that's too long for the X display"); break; } } xu_last = xu; yu_last = yu; } /* Is this path a rectangle in device space? We check this because by calling XFillRectangle (and XDrawRectangle too, if the edging is solid), we can save a bit of time, or at least network bandwidth. */ /* N.B. This checks only for rectangles traced counterclockwise from the lower left corner. Should improve this. */ #define IS_A_RECTANGLE(len,q) \ ((len) == 5 && (q)[0].x == (q)[4].x && (q)[0].y == (q)[4].y && \ (q)[0].x == (q)[3].x && (q)[1].x == (q)[2].x && \ (q)[0].y == (q)[1].y && (q)[2].y == (q)[3].y && \ (q)[0].x < (q)[1].x && (q)[0].y > (q)[2].y) /* note flipped-y convention */ is_a_rectangle = IS_A_RECTANGLE(polyline_len, xarray); /* N.B. If a rectangle, upper left corner = q[3], and also, width = q[1].x - q[0].x and height = q[0].y - q[2].y (note flipped-y convention). */ /* compute the square size, and offset of upper left vertex from center of square, that we'll use when handling the notorious special case: all user-space points in the polyline get mapped to a single integer X pixel */ /* FIRST TASK: fill the polygon (if necessary). */ if (_plotter->drawstate->fill_type) /* not transparent, so fill the path */ { int x_polygon_type = (_plotter->drawstate->path->primitive ? Convex : Complex); /* update GC used for filling */ _pl_x_set_attributes (R___(_plotter) X_GC_FOR_FILLING); /* select fill color as foreground color in GC used for filling */ _pl_x_set_fill_color (S___(_plotter)); if (_plotter->x_double_buffering != X_DBL_BUF_NONE) { if (_plotter->drawstate->path->num_segments > 1 && polyline_len == 1) /* special case: all user-space points in the polyline were mapped to a single integer X pixel */ XDrawPoint (_plotter->x_dpy, _plotter->x_drawable3, _plotter->drawstate->x_gc_fill, (int)(xarray[0].x), (int)(xarray[0].y)); else /* general case */ { if (is_a_rectangle) /* call XFillRectangle, for speed */ XFillRectangle (_plotter->x_dpy, _plotter->x_drawable3, _plotter->drawstate->x_gc_fill, (int)(xarray[3].x), (int)(xarray[3].y), (unsigned int)(xarray[1].x - xarray[0].x), /* flipped y */ (unsigned int)(xarray[0].y - xarray[2].y)); else /* not a rectangle, call XFillPolygon */ XFillPolygon (_plotter->x_dpy, _plotter->x_drawable3, _plotter->drawstate->x_gc_fill, xarray, polyline_len, x_polygon_type, CoordModeOrigin); } } else /* not double buffering, no `x_drawable3' */ { if (_plotter->drawstate->path->num_segments > 1 && polyline_len == 1) /* special case: all user-space points in the polyline were mapped to a single integer X pixel. */ { if (_plotter->x_drawable1) XDrawPoint (_plotter->x_dpy, _plotter->x_drawable1, _plotter->drawstate->x_gc_fill, (int)(xarray[0].x), (int)(xarray[0].y)); if (_plotter->x_drawable2) XDrawPoint (_plotter->x_dpy, _plotter->x_drawable2, _plotter->drawstate->x_gc_fill, (int)(xarray[0].x), (int)(xarray[0].y)); } else /* general case */ { if (is_a_rectangle) /* call XFillRectangle, for speed */ { if (_plotter->x_drawable1) XFillRectangle (_plotter->x_dpy, _plotter->x_drawable1, _plotter->drawstate->x_gc_fill, (int)(xarray[3].x), (int)(xarray[3].y), (unsigned int)(xarray[1].x - xarray[0].x), /* flipped y */ (unsigned int)(xarray[0].y - xarray[2].y)); if (_plotter->x_drawable2) XFillRectangle (_plotter->x_dpy, _plotter->x_drawable2, _plotter->drawstate->x_gc_fill, (int)(xarray[3].x), (int)(xarray[3].y), (unsigned int)(xarray[1].x - xarray[0].x), /* flipped y */ (unsigned int)(xarray[0].y - xarray[2].y)); } else /* not a rectangle, call XFillPolygon */ { if (_plotter->x_drawable1) XFillPolygon (_plotter->x_dpy, _plotter->x_drawable1, _plotter->drawstate->x_gc_fill, xarray, polyline_len, x_polygon_type, CoordModeOrigin); if (_plotter->x_drawable2) XFillPolygon (_plotter->x_dpy, _plotter->x_drawable2, _plotter->drawstate->x_gc_fill, xarray, polyline_len, x_polygon_type, CoordModeOrigin); } } } } /* SECOND TASK: edge the polygon (if necessary). */ if (_plotter->drawstate->pen_type) /* pen is present, so edge the path */ { int xloc = 0, yloc = 0; unsigned int sp_size = 1; /* update GC used for drawing */ _pl_x_set_attributes (R___(_plotter) X_GC_FOR_DRAWING); /* select pen color as foreground color in GC used for drawing */ _pl_x_set_pen_color (S___(_plotter)); /* Check first for the special case: all points in the polyline were mapped to a single integer X pixel. If (1) they weren't all the same to begin with, or (2) they were all the same to begin with and the cap mode is "round", then draw as a filled circle of diameter equal to the line width; otherwise draw nothing. (If the circle would have diameter 1 or less, we draw a point instead.) */ if (_plotter->drawstate->path->num_segments > 1 && polyline_len == 1) /* this is the special case, so compute quantities needed for drawing the filled circle */ { int sp_offset; sp_size = (unsigned int)_plotter->drawstate->quantized_device_line_width; if (sp_size == 0) sp_size = 1; sp_offset = (_plotter->drawstate->quantized_device_line_width + 1) / 2; xloc = xarray[0].x - sp_offset; yloc = xarray[0].y - sp_offset; } if (_plotter->x_double_buffering != X_DBL_BUF_NONE) /* double buffering, have a `x_drawable3' to draw into */ { if (_plotter->drawstate->path->num_segments > 1 && polyline_len == 1) /* special case */ { if (identical_user_coordinates == false || _plotter->drawstate->cap_type == PL_CAP_ROUND) { if (sp_size == 1) /* subcase: just draw a point */ XDrawPoint (_plotter->x_dpy, _plotter->x_drawable3, _plotter->drawstate->x_gc_fg, (int)(xarray[0].x), (int)(xarray[0].y)); else /* draw filled circle */ XFillArc(_plotter->x_dpy, _plotter->x_drawable3, _plotter->drawstate->x_gc_fg, xloc, yloc, sp_size, sp_size, 0, 64 * 360); } } else /* general case */ /* NOTE: this code is what libplot uses to draw nearly all polylines, in the case when double buffering is used */ { if (is_a_rectangle && _plotter->drawstate->dash_array_in_effect == false && _plotter->drawstate->line_type == PL_L_SOLID) /* call XDrawRectangle, for speed */ XDrawRectangle (_plotter->x_dpy, _plotter->x_drawable3, _plotter->drawstate->x_gc_fg, (int)(xarray[3].x), (int)(xarray[3].y), (unsigned int)(xarray[1].x - xarray[0].x), /* flipped y */ (unsigned int)(xarray[0].y - xarray[2].y)); else /* can't call XDrawRectangle */ XDrawLines (_plotter->x_dpy, _plotter->x_drawable3, _plotter->drawstate->x_gc_fg, xarray, polyline_len, CoordModeOrigin); } } else /* not double buffering, have no `x_drawable3' */ { if (_plotter->drawstate->path->num_segments > 1 && polyline_len == 1) /* special case */ { if (identical_user_coordinates == false || _plotter->drawstate->cap_type == PL_CAP_ROUND) { if (sp_size == 1) /* subcase: just draw a point */ { if (_plotter->x_drawable1) XDrawPoint (_plotter->x_dpy, _plotter->x_drawable1, _plotter->drawstate->x_gc_fg, (int)(xarray[0].x), (int)(xarray[0].y)); if (_plotter->x_drawable2) XDrawPoint (_plotter->x_dpy, _plotter->x_drawable2, _plotter->drawstate->x_gc_fg, (int)(xarray[0].x), (int)(xarray[0].y)); } else /* draw filled circle */ { if (_plotter->x_drawable1) XFillArc(_plotter->x_dpy, _plotter->x_drawable1, _plotter->drawstate->x_gc_fg, xloc, yloc, sp_size, sp_size, 0, 64 * 360); if (_plotter->x_drawable2) XFillArc(_plotter->x_dpy, _plotter->x_drawable2, _plotter->drawstate->x_gc_fg, xloc, yloc, sp_size, sp_size, 0, 64 * 360); } } } else /* general case */ /* NOTE: this code is what libplot uses to draw nearly all polylines; at least, if double buffering is not used */ { if (is_a_rectangle && _plotter->drawstate->dash_array_in_effect == false && _plotter->drawstate->line_type == PL_L_SOLID) /* call XDrawRectangle, for speed */ { if (_plotter->x_drawable1) XDrawRectangle (_plotter->x_dpy, _plotter->x_drawable1, _plotter->drawstate->x_gc_fg, (int)(xarray[3].x), (int)(xarray[3].y), (unsigned int)(xarray[1].x - xarray[0].x), /* flipped y */ (unsigned int)(xarray[0].y - xarray[2].y)); if (_plotter->x_drawable2) XDrawRectangle (_plotter->x_dpy, _plotter->x_drawable2, _plotter->drawstate->x_gc_fg, (int)(xarray[3].x), (int)(xarray[3].y), (unsigned int)(xarray[1].x - xarray[0].x), /* flipped y */ (unsigned int)(xarray[0].y - xarray[2].y)); } else /* can't use XDrawRectangle() */ { if (_plotter->x_drawable1) XDrawLines (_plotter->x_dpy, _plotter->x_drawable1, _plotter->drawstate->x_gc_fg, xarray, polyline_len, CoordModeOrigin); if (_plotter->x_drawable2) XDrawLines (_plotter->x_dpy, _plotter->x_drawable2, _plotter->drawstate->x_gc_fg, xarray, polyline_len, CoordModeOrigin); } } } } /* reset buffer used for array of XPoint structs */ if (_plotter->drawstate->path->num_segments > 0) { if (heap_storage) free (xarray); /* free malloc'd array of XPoints */ } } break; case (int)PATH_ELLIPSE: { int ninetymult; int x_orientation, y_orientation; int xorigin, yorigin; unsigned int squaresize_x, squaresize_y; plPoint pc; double rx, ry, angle; pc = _plotter->drawstate->path->pc; rx = _plotter->drawstate->path->rx; ry = _plotter->drawstate->path->ry; angle = _plotter->drawstate->path->angle; /* if angle is multiple of 90 degrees, modify to permit use of X11 arc rendering */ ninetymult = IROUND(angle / 90.0); if (angle == (double) (90 * ninetymult)) { angle = 0.0; if (ninetymult % 2) { double temp; temp = rx; rx = ry; ry = temp; } } rx = (rx < 0.0 ? -rx : rx); /* avoid obscure libxmi problems */ ry = (ry < 0.0 ? -ry : ry); /* axes flipped? (by default y-axis is, due to libxmi's flipped-y convention) */ x_orientation = (_plotter->drawstate->transform.m[0] >= 0 ? 1 : -1); y_orientation = (_plotter->drawstate->transform.m[3] >= 0 ? 1 : -1); /* location of `origin' (upper left corner of bounding rect. for ellipse) and width and height; X11's flipped-y convention affects these values */ xorigin = IROUND(XD(pc.x - x_orientation * rx, pc.y - y_orientation * ry)); yorigin = IROUND(YD(pc.x - x_orientation * rx, pc.y - y_orientation * ry)); squaresize_x = (unsigned int)IROUND(XDV(2 * x_orientation * rx, 0.0)); squaresize_y = (unsigned int)IROUND(YDV(0.0, 2 * y_orientation * ry)); /* Because this ellipse object was added to the path buffer, we already know that (1) the user->device frame map preserves coordinate axes, (2) effectively, angle == 0. These are necessary for the libxmi scan-conversion module to do the drawing. */ /* draw ellipse (elliptic arc aligned with the coordinate axes, arc range = 64*360 64'ths of a degree) */ _pl_x_draw_elliptic_arc_internal (R___(_plotter) xorigin, yorigin, squaresize_x, squaresize_y, 0, 64 * 360); } break; default: /* shouldn't happen */ break; } /* maybe flush X output buffer and handle X events (a no-op for XDrawablePlotters, which is overridden for XPlotters) */ _maybe_handle_x_events (S___(_plotter)); }
void GLAPIENTRY _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params) { struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { /* '3.8.2 Sampler Objects' section of the GL-ES 3.0 specification states: * * "An INVALID_OPERATION error is generated if sampler is not the name * of a sampler object previously returned from a call to GenSamplers." * * In desktop GL, an GL_INVALID_VALUE is returned instead. */ _mesa_error(ctx, (_mesa_is_gles(ctx) ? GL_INVALID_OPERATION : GL_INVALID_VALUE), "glGetSamplerParameteriv(sampler %u)", sampler); return; } switch (pname) { case GL_TEXTURE_WRAP_S: *params = sampObj->WrapS; break; case GL_TEXTURE_WRAP_T: *params = sampObj->WrapT; break; case GL_TEXTURE_WRAP_R: *params = sampObj->WrapR; break; case GL_TEXTURE_MIN_FILTER: *params = sampObj->MinFilter; break; case GL_TEXTURE_MAG_FILTER: *params = sampObj->MagFilter; break; case GL_TEXTURE_MIN_LOD: /* GL spec 'Data Conversions' section specifies that floating-point * value in integer Get function is rounded to nearest integer */ *params = IROUND(sampObj->MinLod); break; case GL_TEXTURE_MAX_LOD: /* GL spec 'Data Conversions' section specifies that floating-point * value in integer Get function is rounded to nearest integer */ *params = IROUND(sampObj->MaxLod); break; case GL_TEXTURE_LOD_BIAS: /* GL spec 'Data Conversions' section specifies that floating-point * value in integer Get function is rounded to nearest integer */ *params = IROUND(sampObj->LodBias); break; case GL_TEXTURE_COMPARE_MODE: if (!ctx->Extensions.ARB_shadow) goto invalid_pname; *params = sampObj->CompareMode; break; case GL_TEXTURE_COMPARE_FUNC: if (!ctx->Extensions.ARB_shadow) goto invalid_pname; *params = sampObj->CompareFunc; break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: /* GL spec 'Data Conversions' section specifies that floating-point * value in integer Get function is rounded to nearest integer */ *params = IROUND(sampObj->MaxAnisotropy); break; case GL_TEXTURE_BORDER_COLOR: params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]); params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]); params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]); params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]); break; case GL_TEXTURE_CUBE_MAP_SEAMLESS: if (!ctx->Extensions.AMD_seamless_cubemap_per_texture) goto invalid_pname; *params = sampObj->CubeMapSeamless; break; case GL_TEXTURE_SRGB_DECODE_EXT: if (!ctx->Extensions.EXT_texture_sRGB_decode) goto invalid_pname; *params = (GLenum) sampObj->sRGBDecode; break; default: goto invalid_pname; } return; invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)", _mesa_enum_to_string(pname)); }
void GLAPIENTRY _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params) { struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); sampObj = sampler_parameter_error_check(ctx, sampler, true, "glGetSamplerParameteriv"); if (!sampObj) return; switch (pname) { case GL_TEXTURE_WRAP_S: *params = sampObj->WrapS; break; case GL_TEXTURE_WRAP_T: *params = sampObj->WrapT; break; case GL_TEXTURE_WRAP_R: *params = sampObj->WrapR; break; case GL_TEXTURE_MIN_FILTER: *params = sampObj->MinFilter; break; case GL_TEXTURE_MAG_FILTER: *params = sampObj->MagFilter; break; case GL_TEXTURE_MIN_LOD: /* GL spec 'Data Conversions' section specifies that floating-point * value in integer Get function is rounded to nearest integer */ *params = IROUND(sampObj->MinLod); break; case GL_TEXTURE_MAX_LOD: /* GL spec 'Data Conversions' section specifies that floating-point * value in integer Get function is rounded to nearest integer */ *params = IROUND(sampObj->MaxLod); break; case GL_TEXTURE_LOD_BIAS: /* GL spec 'Data Conversions' section specifies that floating-point * value in integer Get function is rounded to nearest integer */ *params = IROUND(sampObj->LodBias); break; case GL_TEXTURE_COMPARE_MODE: *params = sampObj->CompareMode; break; case GL_TEXTURE_COMPARE_FUNC: *params = sampObj->CompareFunc; break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: /* GL spec 'Data Conversions' section specifies that floating-point * value in integer Get function is rounded to nearest integer */ *params = IROUND(sampObj->MaxAnisotropy); break; case GL_TEXTURE_BORDER_COLOR: params[0] = FLOAT_TO_INT(sampObj->BorderColor.f[0]); params[1] = FLOAT_TO_INT(sampObj->BorderColor.f[1]); params[2] = FLOAT_TO_INT(sampObj->BorderColor.f[2]); params[3] = FLOAT_TO_INT(sampObj->BorderColor.f[3]); break; case GL_TEXTURE_CUBE_MAP_SEAMLESS: if (!ctx->Extensions.AMD_seamless_cubemap_per_texture) goto invalid_pname; *params = sampObj->CubeMapSeamless; break; case GL_TEXTURE_SRGB_DECODE_EXT: if (!ctx->Extensions.EXT_texture_sRGB_decode) goto invalid_pname; *params = (GLenum) sampObj->sRGBDecode; break; default: goto invalid_pname; } return; invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glGetSamplerParameteriv(pname=%s)", _mesa_enum_to_string(pname)); }
void _pl_c_paint_point (S___(Plotter *_plotter)) { double xd, yd; int i_x, i_y; if (_plotter->drawstate->pen_type != 0) /* have a pen to draw with */ { if (_plotter->cgm_marker_type != CGM_M_DOT) /* emit "MARKER TYPE" command */ { int byte_count, data_byte_count, data_len; data_len = 2; /* number of bytes per index */ byte_count = data_byte_count = 0; _cgm_emit_command_header (_plotter->data->page, _plotter->cgm_encoding, CGM_ATTRIBUTE_ELEMENT, 6, data_len, &byte_count, "MARKERTYPE"); _cgm_emit_index (_plotter->data->page, false, _plotter->cgm_encoding, CGM_M_DOT, data_len, &data_byte_count, &byte_count); _cgm_emit_command_terminator (_plotter->data->page, _plotter->cgm_encoding, &byte_count); /* update marker type */ _plotter->cgm_marker_type = CGM_M_DOT; } /* N.B. Should we set the marker size as well? Any good CGM interpreter should draw a dot marker as a very small dot, perhaps a single pixel. */ /* set CGM marker color */ _pl_c_set_pen_color (R___(_plotter) CGM_OBJECT_MARKER); /* compute location in device frame */ xd = XD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y); yd = YD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y); i_x = IROUND(xd); i_y = IROUND(yd); /* emit "POLYMARKER" command, to draw a single marker */ { int byte_count, data_byte_count, data_len; data_len = 1 * 2 * CGM_BINARY_BYTES_PER_INTEGER; byte_count = data_byte_count = 0; _cgm_emit_command_header (_plotter->data->page, _plotter->cgm_encoding, CGM_GRAPHICAL_PRIMITIVE_ELEMENT, 3, data_len, &byte_count, "MARKER"); _cgm_emit_point (_plotter->data->page, false, _plotter->cgm_encoding, i_x, i_y, data_len, &data_byte_count, &byte_count); _cgm_emit_command_terminator (_plotter->data->page, _plotter->cgm_encoding, &byte_count); } } }
/** * Blit color, depth or stencil with GL_NEAREST filtering. */ static void blit_nearest(struct gl_context *ctx, struct gl_framebuffer *readFb, struct gl_framebuffer *drawFb, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield buffer) { struct gl_renderbuffer *readRb, *drawRb = NULL; struct gl_renderbuffer_attachment *readAtt = NULL, *drawAtt = NULL; GLuint numDrawBuffers = 0; GLuint i; 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); enum mode { DIRECT, UNPACK_RGBA_FLOAT, UNPACK_Z_FLOAT, UNPACK_Z_INT, UNPACK_S, } mode = DIRECT; GLubyte *srcMap, *dstMap; GLint srcRowStride, dstRowStride; GLint dstRow; GLint pixelSize = 0; 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: readAtt = &readFb->Attachment[readFb->_ColorReadBufferIndex]; readRb = readFb->_ColorReadBuffer; numDrawBuffers = drawFb->_NumColorDrawBuffers; break; case GL_DEPTH_BUFFER_BIT: readAtt = &readFb->Attachment[BUFFER_DEPTH]; drawAtt = &drawFb->Attachment[BUFFER_DEPTH]; readRb = readAtt->Renderbuffer; drawRb = drawAtt->Renderbuffer; numDrawBuffers = 1; /* Note that for depth/stencil, the formats of src/dst must match. By * using the core helpers for pack/unpack, we avoid needing to handle * masking for things like DEPTH copies of Z24S8. */ if (readRb->Format == MESA_FORMAT_Z_FLOAT32 || readRb->Format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) { mode = UNPACK_Z_FLOAT; } else { mode = UNPACK_Z_INT; } pixelSize = 4; break; case GL_STENCIL_BUFFER_BIT: readAtt = &readFb->Attachment[BUFFER_STENCIL]; drawAtt = &drawFb->Attachment[BUFFER_STENCIL]; readRb = readAtt->Renderbuffer; drawRb = drawAtt->Renderbuffer; numDrawBuffers = 1; mode = UNPACK_S; pixelSize = 1; break; default: _mesa_problem(ctx, "unexpected buffer in blit_nearest()"); return; } /* allocate the src/dst row buffers */ srcBuffer = malloc(MAX_PIXEL_BYTES * srcWidth); dstBuffer = malloc(MAX_PIXEL_BYTES * dstWidth); if (!srcBuffer || !dstBuffer) goto fail_no_memory; /* Blit to all the draw buffers */ for (i = 0; i < numDrawBuffers; i++) { if (buffer == GL_COLOR_BUFFER_BIT) { gl_buffer_index idx = drawFb->_ColorDrawBufferIndexes[i]; if (idx == BUFFER_NONE) continue; drawAtt = &drawFb->Attachment[idx]; drawRb = drawAtt->Renderbuffer; if (!drawRb) continue; if (readRb->Format == drawRb->Format) { mode = DIRECT; pixelSize = _mesa_get_format_bytes(readRb->Format); } else { mode = UNPACK_RGBA_FLOAT; pixelSize = 16; } } /* 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); goto fail; } if ((readRb == drawRb) || (readAtt->Texture && drawAtt->Texture && (readAtt->Texture == drawAtt->Texture))) { /* map whole buffer for read/write */ /* XXX we could be clever and just map the union region of the * source and dest rects. */ GLubyte *map; GLint rowStride; GLint formatSize = _mesa_get_format_bytes(readRb->Format); ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0, readRb->Width, readRb->Height, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, &map, &rowStride); if (!map) { goto fail_no_memory; } srcMap = map + srcYpos * rowStride + srcXpos * formatSize; dstMap = map + dstYpos * rowStride + dstXpos * formatSize; /* this handles overlapping copies */ if (srcY0 < dstY0) { /* copy in reverse (top->down) order */ srcMap += rowStride * (readRb->Height - 1); dstMap += rowStride * (readRb->Height - 1); srcRowStride = -rowStride; dstRowStride = -rowStride; } else { /* copy in normal (bottom->up) order */ srcRowStride = rowStride; dstRowStride = rowStride; } } else { /* different src/dst buffers */ ctx->Driver.MapRenderbuffer(ctx, readRb, srcXpos, srcYpos, srcWidth, srcHeight, GL_MAP_READ_BIT, &srcMap, &srcRowStride); if (!srcMap) { goto fail_no_memory; } ctx->Driver.MapRenderbuffer(ctx, drawRb, dstXpos, dstYpos, dstWidth, dstHeight, GL_MAP_WRITE_BIT, &dstMap, &dstRowStride); if (!dstMap) { ctx->Driver.UnmapRenderbuffer(ctx, readRb); goto fail_no_memory; } } for (dstRow = 0; dstRow < dstHeight; dstRow++) { GLfloat srcRowF = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F; GLint srcRow = IROUND(srcRowF); GLubyte *dstRowStart = dstMap + dstRowStride * dstRow; assert(srcRow >= 0); assert(srcRow < srcHeight); if (invertY) { srcRow = srcHeight - 1 - srcRow; } /* get pixel row from source and resample to match dest width */ if (prevY != srcRow) { GLubyte *srcRowStart = srcMap + srcRowStride * srcRow; switch (mode) { case DIRECT: memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth); break; case UNPACK_RGBA_FLOAT: _mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart, srcBuffer); break; case UNPACK_Z_FLOAT: _mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart, srcBuffer); break; case UNPACK_Z_INT: _mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart, srcBuffer); break; case UNPACK_S: _mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth, srcRowStart, srcBuffer); break; } (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX); prevY = srcRow; } /* store pixel row in destination */ switch (mode) { case DIRECT: memcpy(dstRowStart, dstBuffer, pixelSize * dstWidth); break; case UNPACK_RGBA_FLOAT: _mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer, dstRowStart); break; case UNPACK_Z_FLOAT: _mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer, dstRowStart); break; case UNPACK_Z_INT: _mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer, dstRowStart); break; case UNPACK_S: _mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer, dstRowStart); break; } } ctx->Driver.UnmapRenderbuffer(ctx, readRb); if (drawRb != readRb) { ctx->Driver.UnmapRenderbuffer(ctx, drawRb); } } fail: free(srcBuffer); free(dstBuffer); return; fail_no_memory: free(srcBuffer); free(dstBuffer); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBuffer"); }
void GLAPIENTRY _mesa_PixelStoref( GLenum pname, GLfloat param ) { _mesa_PixelStorei( pname, IROUND(param) ); }
/** * Called via glGetUniform[fiui]v() to get the current value of a uniform. */ extern "C" void _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, GLsizei bufSize, enum glsl_base_type returnType, GLvoid *paramsOut) { struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetUniformfv"); struct gl_uniform_storage *uni; unsigned loc, offset; if (!validate_uniform_parameters(ctx, shProg, location, 1, &loc, &offset, "glGetUniform", true)) return; uni = &shProg->UniformStorage[loc]; { unsigned elements = (uni->type->is_sampler()) ? 1 : uni->type->components(); /* Calculate the source base address *BEFORE* modifying elements to * account for the size of the user's buffer. */ const union gl_constant_value *const src = &uni->storage[offset * elements]; unsigned bytes = sizeof(uni->storage[0]) * elements; if (bytes > (unsigned) bufSize) { elements = bufSize / sizeof(uni->storage[0]); bytes = bufSize; } /* If the return type and the uniform's native type are "compatible," * just memcpy the data. If the types are not compatible, perform a * slower convert-and-copy process. */ if (returnType == uni->type->base_type || ((returnType == GLSL_TYPE_INT || returnType == GLSL_TYPE_UINT || returnType == GLSL_TYPE_SAMPLER) && (uni->type->base_type == GLSL_TYPE_INT || uni->type->base_type == GLSL_TYPE_UINT || uni->type->base_type == GLSL_TYPE_SAMPLER))) { memcpy(paramsOut, src, bytes); } else { union gl_constant_value *const dst = (union gl_constant_value *) paramsOut; /* This code could be optimized by putting the loop inside the switch * statements. However, this is not expected to be * performance-critical code. */ for (unsigned i = 0; i < elements; i++) { switch (returnType) { case GLSL_TYPE_FLOAT: switch (uni->type->base_type) { case GLSL_TYPE_UINT: dst[i].f = (float) src[i].u; break; case GLSL_TYPE_INT: case GLSL_TYPE_SAMPLER: dst[i].f = (float) src[i].i; break; case GLSL_TYPE_BOOL: dst[i].f = src[i].i ? 1.0f : 0.0f; break; default: assert(!"Should not get here."); break; } break; case GLSL_TYPE_INT: case GLSL_TYPE_UINT: switch (uni->type->base_type) { case GLSL_TYPE_FLOAT: /* While the GL 3.2 core spec doesn't explicitly * state how conversion of float uniforms to integer * values works, in section 6.2 "State Tables" on * page 267 it says: * * "Unless otherwise specified, when floating * point state is returned as integer values or * integer state is returned as floating-point * values it is converted in the fashion * described in section 6.1.2" * * That section, on page 248, says: * * "If GetIntegerv or GetInteger64v are called, * a floating-point value is rounded to the * nearest integer..." */ dst[i].i = IROUND(src[i].f); break; case GLSL_TYPE_BOOL: dst[i].i = src[i].i ? 1 : 0; break; default: assert(!"Should not get here."); break; } break; default: assert(!"Should not get here."); break; } } } } }
void _set_common_mi_attributes (plDrawState *drawstate, void * ptr) { int line_style, num_dashes, offset; unsigned int *dashbuf; bool dash_array_allocated = false; miGCAttribute attributes[5]; int values [5]; unsigned int local_dashbuf[PL_MAX_DASH_ARRAY_LEN]; miGC *pGC; pGC = (miGC *)ptr; /* recover passed libxmi GC */ /* set all miGC attributes that are not dash related */ /* set five integer-valued miGC attributes */ attributes[0] = MI_GC_FILL_RULE; values[0] = (drawstate->fill_rule_type == PL_FILL_NONZERO_WINDING ? MI_WINDING_RULE : MI_EVEN_ODD_RULE); attributes[1] = MI_GC_JOIN_STYLE; values[1] = mi_join_style[drawstate->join_type]; attributes[2] = MI_GC_CAP_STYLE; values[2] = mi_cap_style[drawstate->cap_type]; attributes[3] = MI_GC_ARC_MODE; values[3] = MI_ARC_CHORD; /* libplot convention */ attributes[4] = MI_GC_LINE_WIDTH; values[4] = drawstate->quantized_device_line_width; miSetGCAttribs (pGC, 5, attributes, values); /* set a double-valued miGC attribute */ miSetGCMiterLimit (pGC, drawstate->miter_limit); /* now determine and set dashing-related attributes */ if (drawstate->dash_array_in_effect) /* have user-specified dash array */ { int i; num_dashes = drawstate->dash_array_len; if (num_dashes > 0) /* non-solid line type */ { bool odd_length; double min_sing_val, max_sing_val; int dash_cycle_length; /* compute minimum singular value of user->device coordinate map, which we use as a multiplicative factor to convert line widths (cf. g_linewidth.c), dash lengths, etc. */ _matrix_sing_vals (drawstate->transform.m, &min_sing_val, &max_sing_val); line_style = MI_LINE_ON_OFF_DASH; odd_length = (num_dashes & 1 ? true : false); { int array_len; array_len = (odd_length ? 2 : 1) * num_dashes; if (array_len <= PL_MAX_DASH_ARRAY_LEN) dashbuf = local_dashbuf; /* use dash buffer on stack */ else { dashbuf = (unsigned int *)_pl_xmalloc (array_len * sizeof(unsigned int)); dash_array_allocated = true; } } dash_cycle_length = 0; for (i = 0; i < num_dashes; i++) { double unrounded_dashlen; int dashlen; unrounded_dashlen = min_sing_val * drawstate->dash_array[i]; dashlen = IROUND(unrounded_dashlen); dashlen = IMAX(dashlen, 1); dashbuf[i] = (unsigned int)dashlen; dash_cycle_length += dashlen; if (odd_length) { dashbuf[num_dashes + i] = (unsigned int)dashlen; dash_cycle_length += dashlen; } } if (odd_length) num_dashes *= 2; offset = IROUND(min_sing_val * drawstate->dash_offset); if (dash_cycle_length > 0) /* choose an offset in range 0..dash_cycle_length-1 */ { while (offset < 0) offset += dash_cycle_length; offset %= dash_cycle_length; } } else /* zero-length dash array, i.e. solid line type */ { line_style = MI_LINE_SOLID; dashbuf = NULL; offset = 0; } } else /* have one of the canonical line types */ { if (drawstate->line_type == PL_L_SOLID) { line_style = MI_LINE_SOLID; num_dashes = 0; dashbuf = NULL; offset = 0; } else { const int *dash_array; int scale, i; line_style = MI_LINE_ON_OFF_DASH; num_dashes = _pl_g_line_styles[drawstate->line_type].dash_array_len; dash_array = _pl_g_line_styles[drawstate->line_type].dash_array; dashbuf = local_dashbuf; /* it is large enough */ offset = 0; /* scale by line width in terms of pixels, if nonzero */ scale = drawstate->quantized_device_line_width; if (scale <= 0) scale = 1; for (i = 0; i < num_dashes; i++) { int dashlen; dashlen = scale * dash_array[i]; dashlen = IMAX(dashlen, 1); dashbuf[i] = (unsigned int)dashlen; } } } /* set dash-related attributes in libxmi's graphics context */ miSetGCAttrib (pGC, MI_GC_LINE_STYLE, line_style); if (line_style != (int)MI_LINE_SOLID) miSetGCDashes (pGC, num_dashes, dashbuf, offset); if (dash_array_allocated) free (dashbuf); }
static void accum_return(GLcontext *ctx, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; struct gl_renderbuffer *accumRb = fb->Attachment[BUFFER_ACCUM].Renderbuffer; const GLboolean directAccess = (accumRb->GetPointer(ctx, accumRb, 0, 0) != NULL); const GLboolean masking = (!ctx->Color.ColorMask[RCOMP] || !ctx->Color.ColorMask[GCOMP] || !ctx->Color.ColorMask[BCOMP] || !ctx->Color.ColorMask[ACOMP]); static GLchan multTable[32768]; static GLfloat prevMult = 0.0; const GLfloat mult = swrast->_IntegerAccumScaler; const GLint max = MIN2((GLint) (256 / mult), 32767); /* May have to leave optimized accum buffer mode */ if (swrast->_IntegerAccumMode && value != 1.0) rescale_accum(ctx); if (swrast->_IntegerAccumMode && swrast->_IntegerAccumScaler > 0) { /* build lookup table to avoid many floating point multiplies */ GLint j; assert(swrast->_IntegerAccumScaler <= 1.0); if (mult != prevMult) { for (j = 0; j < max; j++) multTable[j] = IROUND((GLfloat) j * mult); prevMult = mult; } } if (accumRb->DataType == GL_SHORT || accumRb->DataType == GL_UNSIGNED_SHORT) { const GLfloat scale = value * CHAN_MAXF / ACCUM_SCALE16; GLuint buffer; GLint i; /* XXX maybe transpose the 'i' and 'buffer' loops??? */ for (i = 0; i < height; i++) { GLshort accumRow[4 * MAX_WIDTH]; GLshort *acc; SWspan span; /* init color span */ INIT_SPAN(span, GL_BITMAP); span.end = width; span.arrayMask = SPAN_RGBA; span.x = xpos; span.y = ypos + i; if (directAccess) { acc = (GLshort *) accumRb->GetPointer(ctx, accumRb, xpos, ypos +i); } else { accumRb->GetRow(ctx, accumRb, width, xpos, ypos + i, accumRow); acc = accumRow; } /* get the colors to return */ if (swrast->_IntegerAccumMode) { GLint j; for (j = 0; j < width; j++) { ASSERT(acc[j * 4 + 0] < max); ASSERT(acc[j * 4 + 1] < max); ASSERT(acc[j * 4 + 2] < max); ASSERT(acc[j * 4 + 3] < max); span.array->rgba[j][RCOMP] = multTable[acc[j * 4 + 0]]; span.array->rgba[j][GCOMP] = multTable[acc[j * 4 + 1]]; span.array->rgba[j][BCOMP] = multTable[acc[j * 4 + 2]]; span.array->rgba[j][ACOMP] = multTable[acc[j * 4 + 3]]; } } else { /* scaled integer (or float) accum buffer */ GLint j; for (j = 0; j < width; j++) { #if CHAN_BITS==32 GLchan r = acc[j * 4 + 0] * scale; GLchan g = acc[j * 4 + 1] * scale; GLchan b = acc[j * 4 + 2] * scale; GLchan a = acc[j * 4 + 3] * scale; #else GLint r = IROUND( (GLfloat) (acc[j * 4 + 0]) * scale ); GLint g = IROUND( (GLfloat) (acc[j * 4 + 1]) * scale ); GLint b = IROUND( (GLfloat) (acc[j * 4 + 2]) * scale ); GLint a = IROUND( (GLfloat) (acc[j * 4 + 3]) * scale ); #endif span.array->rgba[j][RCOMP] = CLAMP( r, 0, CHAN_MAX ); span.array->rgba[j][GCOMP] = CLAMP( g, 0, CHAN_MAX ); span.array->rgba[j][BCOMP] = CLAMP( b, 0, CHAN_MAX ); span.array->rgba[j][ACOMP] = CLAMP( a, 0, CHAN_MAX ); } } /* store colors */ for (buffer = 0; buffer < fb->_NumColorDrawBuffers; buffer++) { struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buffer]; if (masking) { _swrast_mask_rgba_span(ctx, rb, &span); } rb->PutRow(ctx, rb, width, xpos, ypos + i, span.array->rgba, NULL); } } } else { /* other types someday */ } }
void GLAPIENTRY _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLenum type ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (ctx->NewState) { _mesa_update_state(ctx); } if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyPixels (invalid fragment program)"); return; } if (width < 0 || height < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)"); return; } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glCopyPixels(incomplete framebuffer)" ); return; } if (!_mesa_source_buffer_exists(ctx, type) || !_mesa_dest_buffer_exists(ctx, type)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyPixels(missing source or dest buffer)"); return; } if (!ctx->Current.RasterPosValid) { return; } if (ctx->RenderMode == GL_RENDER) { /* Round to satisfy conformance tests (matches SGI's OpenGL) */ GLint destx = IROUND(ctx->Current.RasterPos[0]); GLint desty = IROUND(ctx->Current.RasterPos[1]); ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type ); } else if (ctx->RenderMode == GL_FEEDBACK) { FLUSH_CURRENT( ctx, 0 ); FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterIndex, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } }
/** * Called via glGetUniform[fiui]v() to get the current value of a uniform. */ extern "C" void _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, GLsizei bufSize, enum glsl_base_type returnType, GLvoid *paramsOut) { struct gl_shader_program *shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetUniformfv"); unsigned offset; struct gl_uniform_storage *const uni = validate_uniform_parameters(ctx, shProg, location, 1, &offset, "glGetUniform"); if (uni == NULL) { /* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1 * spec says: * * "The error INVALID_OPERATION is generated if program has not been * linked successfully, or if location is not a valid location for * program." * * For glUniform, page 82 (page 96 of the PDF) of the OpenGL 2.1 spec * says: * * "If the value of location is -1, the Uniform* commands will * silently ignore the data passed in, and the current uniform * values will not be changed." * * Allowing -1 for the location parameter of glUniform allows * applications to avoid error paths in the case that, for example, some * uniform variable is removed by the compiler / linker after * optimization. In this case, the new value of the uniform is dropped * on the floor. For the case of glGetUniform, there is nothing * sensible to do for a location of -1. * * If the location was -1, validate_unfirom_parameters will return NULL * without raising an error. Raise the error here. */ if (location == -1) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniform(location=%d)", location); } return; } if ((uni->type->base_type == GLSL_TYPE_DOUBLE && returnType != GLSL_TYPE_DOUBLE) || (uni->type->base_type != GLSL_TYPE_DOUBLE && returnType == GLSL_TYPE_DOUBLE)) { _mesa_error( ctx, GL_INVALID_OPERATION, "glGetnUniform*vARB(incompatible uniform types)"); return; } { unsigned elements = (uni->type->is_sampler()) ? 1 : uni->type->components(); const int dmul = uni->type->base_type == GLSL_TYPE_DOUBLE ? 2 : 1; /* Calculate the source base address *BEFORE* modifying elements to * account for the size of the user's buffer. */ const union gl_constant_value *const src = &uni->storage[offset * elements * dmul]; assert(returnType == GLSL_TYPE_FLOAT || returnType == GLSL_TYPE_INT || returnType == GLSL_TYPE_UINT || returnType == GLSL_TYPE_DOUBLE); /* doubles have a different size than the other 3 types */ unsigned bytes = sizeof(src[0]) * elements * dmul; if (bufSize < 0 || bytes > (unsigned) bufSize) { _mesa_error( ctx, GL_INVALID_OPERATION, "glGetnUniform*vARB(out of bounds: bufSize is %d," " but %u bytes are required)", bufSize, bytes ); return; } /* If the return type and the uniform's native type are "compatible," * just memcpy the data. If the types are not compatible, perform a * slower convert-and-copy process. */ if (returnType == uni->type->base_type || ((returnType == GLSL_TYPE_INT || returnType == GLSL_TYPE_UINT) && (uni->type->base_type == GLSL_TYPE_INT || uni->type->base_type == GLSL_TYPE_UINT || uni->type->base_type == GLSL_TYPE_SAMPLER || uni->type->base_type == GLSL_TYPE_IMAGE))) { memcpy(paramsOut, src, bytes); } else { union gl_constant_value *const dst = (union gl_constant_value *) paramsOut; /* This code could be optimized by putting the loop inside the switch * statements. However, this is not expected to be * performance-critical code. */ for (unsigned i = 0; i < elements; i++) { switch (returnType) { case GLSL_TYPE_FLOAT: switch (uni->type->base_type) { case GLSL_TYPE_UINT: dst[i].f = (float) src[i].u; break; case GLSL_TYPE_INT: case GLSL_TYPE_SAMPLER: case GLSL_TYPE_IMAGE: dst[i].f = (float) src[i].i; break; case GLSL_TYPE_BOOL: dst[i].f = src[i].i ? 1.0f : 0.0f; break; default: assert(!"Should not get here."); break; } break; case GLSL_TYPE_INT: case GLSL_TYPE_UINT: switch (uni->type->base_type) { case GLSL_TYPE_FLOAT: /* While the GL 3.2 core spec doesn't explicitly * state how conversion of float uniforms to integer * values works, in section 6.2 "State Tables" on * page 267 it says: * * "Unless otherwise specified, when floating * point state is returned as integer values or * integer state is returned as floating-point * values it is converted in the fashion * described in section 6.1.2" * * That section, on page 248, says: * * "If GetIntegerv or GetInteger64v are called, * a floating-point value is rounded to the * nearest integer..." */ dst[i].i = IROUND(src[i].f); break; case GLSL_TYPE_BOOL: dst[i].i = src[i].i ? 1 : 0; break; default: assert(!"Should not get here."); break; } break; default: assert(!"Should not get here."); break; } } } } }
static void GLAPIENTRY _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLenum type ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (width < 0 || height < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)"); return; } /* Note: more detailed 'type' checking is done by the * _mesa_source/dest_buffer_exists() calls below. That's where we * check if the stencil buffer exists, etc. */ if (type != GL_COLOR && type != GL_DEPTH && type != GL_STENCIL && type != GL_DEPTH_STENCIL) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)", _mesa_lookup_enum_by_nr(type)); return; } /* We're not using the current vertex program, and the driver may install * it's own. */ _mesa_set_vp_override(ctx, GL_TRUE); if (ctx->NewState) { _mesa_update_state(ctx); } if (!valid_fragment_program(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyPixels (invalid fragment program)"); goto end; } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glCopyPixels(incomplete framebuffer)" ); goto end; } if (!_mesa_source_buffer_exists(ctx, type) || !_mesa_dest_buffer_exists(ctx, type)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyPixels(missing source or dest buffer)"); goto end; } if (!ctx->Current.RasterPosValid || width ==0 || height == 0) { goto end; /* no-op, not an error */ } if (ctx->RenderMode == GL_RENDER) { /* Round to satisfy conformance tests (matches SGI's OpenGL) */ if (width > 0 && height > 0) { GLint destx = IROUND(ctx->Current.RasterPos[0]); GLint desty = IROUND(ctx->Current.RasterPos[1]); ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type ); } } else if (ctx->RenderMode == GL_FEEDBACK) { FLUSH_CURRENT( ctx, 0 ); _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterIndex, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } end: _mesa_set_vp_override(ctx, GL_FALSE); }
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 ); }
/* * Execute glDrawPixels */ static void GLAPIENTRY _mesa_DrawPixels( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" ); return; } /* We're not using the current vertex program, and the driver may install * it's own. */ _mesa_set_vp_override(ctx, GL_TRUE); if (ctx->NewState) { _mesa_update_state(ctx); } if (!valid_fragment_program(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels (invalid fragment program)"); goto end; } if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) { /* the error was already recorded */ goto end; } if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "glDrawPixels(incomplete framebuffer)" ); goto end; } if (!ctx->Current.RasterPosValid) { goto end; /* no-op, not an error */ } if (ctx->RenderMode == GL_RENDER) { if (width > 0 && height > 0) { /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ GLint x = IROUND(ctx->Current.RasterPos[0]); GLint y = IROUND(ctx->Current.RasterPos[1]); if (ctx->Unpack.BufferObj->Name) { /* unpack from PBO */ if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, format, type, pixels)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(invalid PBO access)"); goto end; } if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(PBO is mapped)"); goto end; } } ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type, &ctx->Unpack, pixels); } } else if (ctx->RenderMode == GL_FEEDBACK) { /* Feedback the current raster pos info */ FLUSH_CURRENT( ctx, 0 ); _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterIndex, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } end: _mesa_set_vp_override(ctx, GL_FALSE); }
/*********************************************************************** * X11DRV_ExtTextOut */ BOOL CDECL X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags, const RECT *lprect, LPCWSTR wstr, UINT count, const INT *lpDx ) { unsigned int i; fontObject* pfo; XFontStruct* font; BOOL rotated = FALSE; XChar2b *str2b = NULL; BOOL dibUpdateFlag = FALSE; BOOL result = TRUE; HRGN saved_region = 0; if(physDev->has_gdi_font) return X11DRV_XRender_ExtTextOut(physDev, x, y, flags, lprect, wstr, count, lpDx); if (!X11DRV_SetupGCForText( physDev )) return TRUE; pfo = XFONT_GetFontObject( physDev->font ); font = pfo->fs; if (pfo->lf.lfEscapement && pfo->lpX11Trans) rotated = TRUE; TRACE("hdc=%p df=%04x %d,%d %s, %d flags=%d lpDx=%p\n", physDev->hdc, (UINT16)(physDev->font), x, y, debugstr_wn (wstr, count), count, flags, lpDx); if (lprect != NULL) TRACE("\trect=(%d,%d - %d,%d)\n", lprect->left, lprect->top, lprect->right, lprect->bottom ); /* Draw the rectangle */ if (flags & ETO_OPAQUE) { X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod ); dibUpdateFlag = TRUE; wine_tsx11_lock(); XSetForeground( gdi_display, physDev->gc, physDev->backgroundPixel ); XFillRectangle( gdi_display, physDev->drawable, physDev->gc, physDev->dc_rect.left + lprect->left, physDev->dc_rect.top + lprect->top, lprect->right - lprect->left, lprect->bottom - lprect->top ); wine_tsx11_unlock(); } if (!count) goto END; /* Nothing more to do */ /* Set the clip region */ if (flags & ETO_CLIPPED) { HRGN clip_region; clip_region = CreateRectRgnIndirect( lprect ); /* make a copy of the current device region */ saved_region = CreateRectRgn( 0, 0, 0, 0 ); CombineRgn( saved_region, physDev->region, 0, RGN_COPY ); X11DRV_SetDeviceClipping( physDev, saved_region, clip_region ); DeleteObject( clip_region ); } /* Draw the text background if necessary */ if (!dibUpdateFlag) { X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod ); dibUpdateFlag = TRUE; } /* Draw the text (count > 0 verified) */ if (!(str2b = X11DRV_cptable[pfo->fi->cptable].punicode_to_char2b( pfo, wstr, count ))) goto FAIL; wine_tsx11_lock(); XSetForeground( gdi_display, physDev->gc, physDev->textPixel ); wine_tsx11_unlock(); if(!rotated) { if (!lpDx) { X11DRV_cptable[pfo->fi->cptable].pDrawString( pfo, gdi_display, physDev->drawable, physDev->gc, physDev->dc_rect.left + x, physDev->dc_rect.top + y, str2b, count ); } else { XTextItem16 *items, *pitem; pitem = items = HeapAlloc( GetProcessHeap(), 0, count * sizeof(XTextItem16) ); if(items == NULL) goto FAIL; for(i = 0; i < count; i++) { pitem->chars = str2b + i; pitem->delta = lpDx[i]; pitem->nchars = 1; pitem->font = None; pitem++; } X11DRV_cptable[pfo->fi->cptable].pDrawText( pfo, gdi_display, physDev->drawable, physDev->gc, physDev->dc_rect.left + x, physDev->dc_rect.top + y, items, pitem - items ); HeapFree( GetProcessHeap(), 0, items ); } } else /* rotated */ { /* have to render character by character. */ double offset = 0.0; UINT i; for (i=0; i<count; i++) { int char_metric_offset = str2b[i].byte2 + (str2b[i].byte1 << 8) - font->min_char_or_byte2; int x_i = IROUND((double) (physDev->dc_rect.left + x) + offset * pfo->lpX11Trans->a / pfo->lpX11Trans->pixelsize ); int y_i = IROUND((double) (physDev->dc_rect.top + y) - offset * pfo->lpX11Trans->b / pfo->lpX11Trans->pixelsize ); X11DRV_cptable[pfo->fi->cptable].pDrawString( pfo, gdi_display, physDev->drawable, physDev->gc, x_i, y_i, &str2b[i], 1); if (lpDx) { offset += lpDx[i]; } else { offset += (double) (font->per_char ? font->per_char[char_metric_offset].attributes: font->min_bounds.attributes) * pfo->lpX11Trans->pixelsize / 1000.0; } } } HeapFree( GetProcessHeap(), 0, str2b ); if (flags & ETO_CLIPPED) { /* restore the device region */ X11DRV_SetDeviceClipping( physDev, saved_region, 0 ); DeleteObject( saved_region ); } goto END; FAIL: HeapFree( GetProcessHeap(), 0, str2b ); result = FALSE; END: if (dibUpdateFlag) X11DRV_UnlockDIBSection( physDev, TRUE ); return result; }
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; }