Ejemplo n.º 1
0
void r600_need_cs_space(struct r600_context *ctx, unsigned num_dw,
			boolean count_draw_in)
{
	struct radeon_winsys_cs *dma = ctx->b.dma.cs;

	/* Flush the DMA IB if it's not empty. */
	if (dma && dma->cdw)
		ctx->b.dma.flush(ctx, RADEON_FLUSH_ASYNC, NULL);

	if (!ctx->b.ws->cs_memory_below_limit(ctx->b.gfx.cs, ctx->b.vram, ctx->b.gtt)) {
		ctx->b.gtt = 0;
		ctx->b.vram = 0;
		ctx->b.gfx.flush(ctx, RADEON_FLUSH_ASYNC, NULL);
		return;
	}
	/* all will be accounted once relocation are emited */
	ctx->b.gtt = 0;
	ctx->b.vram = 0;

	/* The number of dwords we already used in the CS so far. */
	num_dw += ctx->b.gfx.cs->cdw;

	if (count_draw_in) {
		uint64_t mask;

		/* The number of dwords all the dirty states would take. */
		mask = ctx->dirty_atoms;
		while (mask != 0) {
			num_dw += ctx->atoms[u_bit_scan64(&mask)]->num_dw;
			if (ctx->screen->b.trace_bo) {
				num_dw += R600_TRACE_CS_DWORDS;
			}
		}

		/* The upper-bound of how much space a draw command would take. */
		num_dw += R600_MAX_FLUSH_CS_DWORDS + R600_MAX_DRAW_CS_DWORDS;
		if (ctx->screen->b.trace_bo) {
			num_dw += R600_TRACE_CS_DWORDS;
		}
	}

	/* Count in queries_suspend. */
	num_dw += ctx->b.num_cs_dw_nontimer_queries_suspend +
		  ctx->b.num_cs_dw_timer_queries_suspend;

	/* Count in streamout_end at the end of CS. */
	if (ctx->b.streamout.begin_emitted) {
		num_dw += ctx->b.streamout.num_dw_for_end;
	}

	/* SX_MISC */
	if (ctx->b.chip_class == R600) {
		num_dw += 3;
	}

	/* Count in framebuffer cache flushes at the end of CS. */
	num_dw += R600_MAX_FLUSH_CS_DWORDS;

	/* The fence at the end of CS. */
	num_dw += 10;

	/* Flush if there's not enough space. */
	if (num_dw > ctx->b.gfx.cs->max_dw) {
		ctx->b.gfx.flush(ctx, RADEON_FLUSH_ASYNC, NULL);
	}
}
Ejemplo n.º 2
0
/**
 * Copy the active vertex's values to the ctx->Current fields.
 */
static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
{
   struct gl_context *ctx = exec->ctx;
   struct vbo_context *vbo = vbo_context(ctx);
   GLbitfield64 enabled = exec->vtx.enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));

   while (enabled) {
      const int i = u_bit_scan64(&enabled);

      /* Note: the exec->vtx.current[i] pointers point into the
       * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
       */
      GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
      fi_type tmp[8]; /* space for doubles */
      int dmul = exec->vtx.attrtype[i] == GL_DOUBLE ? 2 : 1;

      assert(exec->vtx.attrsz[i]);

      if (exec->vtx.attrtype[i] == GL_DOUBLE) {
         memset(tmp, 0, sizeof(tmp));
         memcpy(tmp, exec->vtx.attrptr[i], exec->vtx.attrsz[i] * sizeof(GLfloat));
      } else {
         COPY_CLEAN_4V_TYPE_AS_UNION(tmp,
                                     exec->vtx.attrsz[i],
                                     exec->vtx.attrptr[i],
                                     exec->vtx.attrtype[i]);
      }

      if (exec->vtx.attrtype[i] != vbo->currval[i].Type ||
          memcmp(current, tmp, 4 * sizeof(GLfloat) * dmul) != 0) {
         memcpy(current, tmp, 4 * sizeof(GLfloat) * dmul);
	 
         /* Given that we explicitly state size here, there is no need
          * for the COPY_CLEAN above, could just copy 16 bytes and be
          * done.  The only problem is when Mesa accesses ctx->Current
          * directly.
          */
         /* Size here is in components - not bytes */
         vbo->currval[i].Size = exec->vtx.attrsz[i] / dmul;
         vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat) * dmul;
         vbo->currval[i].Type = exec->vtx.attrtype[i];
         vbo->currval[i].Integer =
            vbo_attrtype_to_integer_flag(exec->vtx.attrtype[i]);
         vbo->currval[i].Doubles =
            vbo_attrtype_to_double_flag(exec->vtx.attrtype[i]);

         /* This triggers rather too much recalculation of Mesa state
          * that doesn't get used (eg light positions).
          */
         if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
             i <= VBO_ATTRIB_MAT_BACK_INDEXES)
            ctx->NewState |= _NEW_LIGHT;

         ctx->NewState |= _NEW_CURRENT_ATTRIB;
      }
   }

   /* Colormaterial -- this kindof sucks.
    */
   if (ctx->Light.ColorMaterialEnabled &&
       exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
      _mesa_update_color_material(ctx, 
				  ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
   }
}
Ejemplo n.º 3
0
/**
 * Flush existing data, set new attrib size, replay copied vertices.
 * This is called when we transition from a small vertex attribute size
 * to a larger one.  Ex: glTexCoord2f -> glTexCoord4f.
 * We need to go back over the previous 2-component texcoords and insert
 * zero and one values.
 */ 
static void
vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
                             GLuint attr, GLuint newSize )
{
   struct gl_context *ctx = exec->ctx;
   struct vbo_context *vbo = vbo_context(ctx);
   const GLint lastcount = exec->vtx.vert_count;
   fi_type *old_attrptr[VBO_ATTRIB_MAX];
   const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */
   const GLuint oldSize = exec->vtx.attrsz[attr];
   GLuint i;

   /* Run pipeline on current vertices, copy wrapped vertices
    * to exec->vtx.copied.
    */
   vbo_exec_wrap_buffers( exec );

   if (unlikely(exec->vtx.copied.nr)) {
      /* We're in the middle of a primitive, keep the old vertex
       * format around to be able to translate the copied vertices to
       * the new format.
       */
      memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
   }

   if (unlikely(oldSize)) {
      /* Do a COPY_TO_CURRENT to ensure back-copying works for the
       * case when the attribute already exists in the vertex and is
       * having its size increased.
       */
      vbo_exec_copy_to_current( exec );
   }

   /* Heuristic: Attempt to isolate attributes received outside
    * begin/end so that they don't bloat the vertices.
    */
   if (!_mesa_inside_begin_end(ctx) &&
       !oldSize && lastcount > 8 && exec->vtx.vertex_size) {
      vbo_exec_copy_to_current( exec );
      reset_attrfv( exec );
   }

   /* Fix up sizes:
    */
   exec->vtx.attrsz[attr] = newSize;
   exec->vtx.vertex_size += newSize - oldSize;
   exec->vtx.max_vert = vbo_compute_max_verts(exec);
   exec->vtx.vert_count = 0;
   exec->vtx.buffer_ptr = exec->vtx.buffer_map;
   exec->vtx.enabled |= BITFIELD64_BIT(attr);

   if (unlikely(oldSize)) {
      /* Size changed, recalculate all the attrptr[] values
       */
      fi_type *tmp = exec->vtx.vertex;

      for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
	 if (exec->vtx.attrsz[i]) {
	    exec->vtx.attrptr[i] = tmp;
	    tmp += exec->vtx.attrsz[i];
	 }
	 else
	    exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
      }

      /* Copy from current to repopulate the vertex with correct
       * values.
       */
      vbo_exec_copy_from_current( exec );
   }
   else {
      /* Just have to append the new attribute at the end */
      exec->vtx.attrptr[attr] = exec->vtx.vertex +
        exec->vtx.vertex_size - newSize;
   }

   /* Replay stored vertices to translate them
    * to new format here.
    *
    * -- No need to replay - just copy piecewise
    */
   if (unlikely(exec->vtx.copied.nr)) {
      fi_type *data = exec->vtx.copied.buffer;
      fi_type *dest = exec->vtx.buffer_ptr;

      assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);

      for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
         GLbitfield64 enabled = exec->vtx.enabled;
         while (enabled) {
            const int j = u_bit_scan64(&enabled);
	    GLuint sz = exec->vtx.attrsz[j];
            GLint old_offset = old_attrptr[j] - exec->vtx.vertex;
            GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;

            assert(sz);

            if (j == attr) {
               if (oldSize) {
                  fi_type tmp[4];
                  COPY_CLEAN_4V_TYPE_AS_UNION(tmp, oldSize,
                                              data + old_offset,
                                              exec->vtx.attrtype[j]);
                  COPY_SZ_4V(dest + new_offset, newSize, tmp);
               } else {
                  fi_type *current = (fi_type *)vbo->currval[j].Ptr;
                  COPY_SZ_4V(dest + new_offset, sz, current);
               }
            }
            else {
               COPY_SZ_4V(dest + new_offset, sz, data + old_offset);
            }
	 }

	 data += old_vtx_size;
	 dest += exec->vtx.vertex_size;
      }

      exec->vtx.buffer_ptr = dest;
      exec->vtx.vert_count += exec->vtx.copied.nr;
      exec->vtx.copied.nr = 0;
   }
}
Ejemplo n.º 4
0
/**
 * After playback, copy everything but the position from the
 * last vertex to the saved state
 */
static void
_playback_copy_to_current(struct gl_context *ctx,
                          const struct vbo_save_vertex_list *node)
{
   struct vbo_context *vbo = vbo_context(ctx);
   fi_type vertex[VBO_ATTRIB_MAX * 4];
   fi_type *data;
   GLbitfield64 mask;
   GLuint offset;

   if (node->current_size == 0)
      return;

   if (node->current_data) {
      data = node->current_data;
   }
   else {
      data = vertex;

      if (node->count)
         offset = (node->buffer_offset + 
                   (node->count-1) * node->vertex_size * sizeof(GLfloat));
      else
         offset = node->buffer_offset;

      ctx->Driver.GetBufferSubData( ctx, offset,
                                    node->vertex_size * sizeof(GLfloat), 
                                    data, node->vertex_store->bufferobj );

      data += node->attrsz[0]; /* skip vertex position */
   }

   mask = node->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
   while (mask) {
      const int i = u_bit_scan64(&mask);
      fi_type *current = (fi_type *)vbo->currval[i].Ptr;
      fi_type tmp[4];
      assert(node->attrsz[i]);

      COPY_CLEAN_4V_TYPE_AS_UNION(tmp,
                                  node->attrsz[i],
                                  data,
                                  node->attrtype[i]);

      if (node->attrtype[i] != vbo->currval[i].Type ||
          memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) {
         memcpy(current, tmp, 4 * sizeof(GLfloat));
         
         vbo->currval[i].Size = node->attrsz[i];
         vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
         vbo->currval[i].Type = node->attrtype[i];
         vbo->currval[i].Integer =
            vbo_attrtype_to_integer_flag(node->attrtype[i]);

         if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
             i <= VBO_ATTRIB_LAST_MATERIAL)
            ctx->NewState |= _NEW_LIGHT;

         ctx->NewState |= _NEW_CURRENT_ATTRIB;
      }

      data += node->attrsz[i];
   }

   /* Colormaterial -- this kindof sucks.
    */
   if (ctx->Light.ColorMaterialEnabled) {
      _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
   }

   /* CurrentExecPrimitive
    */
   if (node->prim_count) {
      const struct _mesa_prim *prim = &node->prim[node->prim_count - 1];
      if (prim->end)
	 ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
      else
	 ctx->Driver.CurrentExecPrimitive = prim->mode;
   }
}