Example #1
0
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;
    }
}
Example #2
0
/*
 * 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. */
   }
}
Example #3
0
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
  
}
Example #4
0
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++;
}
Example #5
0
/**
 * 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;
        }
    }
}
Example #6
0
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] );
   }
}
Example #7
0
/*
 * 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] );
      }
   }
}
Example #8
0
/**
 * 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;
         }
      }
   }
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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;
    }
}
Example #12
0
/*
 * 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);
   }
}
Example #13
0
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);
   }
}
Example #14
0
/*
 * 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;
}
Example #15
0
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));
}
Example #16
0
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));
}
Example #18
0
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);
      }
    }
}
Example #19
0
/**
 * 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");
}
Example #20
0
void GLAPIENTRY
_mesa_PixelStoref( GLenum pname, GLfloat param )
{
    _mesa_PixelStorei( pname, IROUND(param) );
}
Example #21
0
/**
 * 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;
	    }
	 }
      }
   }
}
Example #22
0
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 */
   }
}
Example #24
0
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. */
   }
}
Example #25
0
/**
 * 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;
	    }
	 }
      }
   }
}
Example #26
0
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);
}
Example #27
0
static void GLAPIENTRY
_mesa_GetnMapivARB( GLenum target, GLenum query, GLsizei bufSize, GLint *v )
{
   GET_CURRENT_CONTEXT(ctx);
   struct gl_1d_map *map1d;
   struct gl_2d_map *map2d;
   GLuint i, n;
   GLfloat *data;
   GLuint comps;
   GLsizei numBytes;

   ASSERT_OUTSIDE_BEGIN_END(ctx);

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

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

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

overflow:
   _mesa_error( ctx, GL_INVALID_OPERATION,
               "glGetnMapivARB(out of bounds: bufSize is %d,"
               " but %d bytes are required)", bufSize, numBytes );
}
Example #28
0
/*
 * 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);
}
Example #29
0
File: text.c Project: bilboed/wine
/***********************************************************************
 *           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;
}
Example #30
0
File: eval.c Project: GYGit/reactos
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;
}