Ejemplo n.º 1
0
void
emit_DrawArrays_old( GLenum mode, GLint first, GLsizei count )
{
    __GLXcontext *gc = __glXGetCurrentContext();
    const __GLXattribute * state = 
       (const __GLXattribute *)(gc->client_state_private);
    struct array_state_vector * arrays = state->array_state;

    GLubyte * pc;
    size_t elements_per_request;
    unsigned total_requests = 0;
    unsigned i;
    size_t total_sent = 0;


    pc = emit_DrawArrays_header_old( gc, arrays, & elements_per_request,
				     & total_requests, mode, count);

    
    /* Write the arrays.
     */

    if ( total_requests == 0 ) {
	assert( elements_per_request >= count );

	for ( i = 0 ; i < count ; i++ ) {
	    pc = emit_element_old( pc, arrays, i + first );
	}

	assert( pc <= gc->bufEnd );

	gc->pc = pc;
	if ( gc->pc > gc->limit ) {
	    (void) __glXFlushRenderBuffer(gc, gc->pc);
	}
    }
    else {
	unsigned req;


	for ( req = 2 ; req <= total_requests ; req++ ) {
	    if ( count < elements_per_request ) {
		elements_per_request = count;
	    }

	    pc = gc->pc;
	    for ( i = 0 ; i < elements_per_request ; i++ ) {
		pc = emit_element_old( pc, arrays, i + first );
	    }

	    first += elements_per_request;

	    total_sent += (size_t) (pc - gc->pc);
	    __glXSendLargeChunk( gc, req, total_requests, gc->pc,
				 pc - gc->pc );

	    count -= elements_per_request;
	}
    }
}
Ejemplo n.º 2
0
/**
 * Send a command that is too large for the GLXRender protocol request.
 *
 * Send a large command, one that is too large for some reason to
 * send using the GLXRender protocol request.  One reason to send
 * a large command is to avoid copying the data.
 *
 * \param ctx        GLX context
 * \param header     Header data.
 * \param headerLen  Size, in bytes, of the header data.  It is assumed that
 *                   the header data will always be small enough to fit in
 *                   a single X protocol packet.
 * \param data       Command data.
 * \param dataLen    Size, in bytes, of the command data.
 */
_X_HIDDEN void
__glXSendLargeCommand(struct glx_context * ctx,
                      const GLvoid * header, GLint headerLen,
                      const GLvoid * data, GLint dataLen)
{
   GLint maxSize;
   GLint totalRequests, requestNumber;

   /*
    ** Calculate the maximum amount of data can be stuffed into a single
    ** packet.  sz_xGLXRenderReq is added because bufSize is the maximum
    ** packet size minus sz_xGLXRenderReq.
    */
   maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
   totalRequests = 1 + (dataLen / maxSize);
   if (dataLen % maxSize)
      totalRequests++;

   /*
    ** Send all of the command, except the large array, as one request.
    */
   assert(headerLen <= maxSize);
   __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);

   /*
    ** Send enough requests until the whole array is sent.
    */
   for (requestNumber = 2; requestNumber <= (totalRequests - 1);
        requestNumber++) {
      __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
      data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
      dataLen -= maxSize;
      assert(dataLen > 0);
   }

   assert(dataLen <= maxSize);
   __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
}
Ejemplo n.º 3
0
void
emit_DrawElements_old( GLenum mode, GLsizei count, GLenum type,
		       const GLvoid *indices )
{
    __GLXcontext *gc = __glXGetCurrentContext();
    const __GLXattribute * state = 
       (const __GLXattribute *)(gc->client_state_private);
    struct array_state_vector * arrays = state->array_state;

    GLubyte * pc;
    size_t elements_per_request;
    unsigned total_requests = 0;
    unsigned i;
    unsigned req;


    pc = emit_DrawArrays_header_old( gc, arrays, & elements_per_request,
				     & total_requests, mode, count);

    
    /* Write the arrays.
     */

    req = 2;
    while ( count > 0 ) {
	if ( count < elements_per_request ) {
	    elements_per_request = count;
	}

	switch( type ) {
	case GL_UNSIGNED_INT: {
	    const GLuint   * ui_ptr = (const GLuint   *) indices;

	    for ( i = 0 ; i < elements_per_request ; i++ ) {
		const GLint index = (GLint) *(ui_ptr++);
		pc = emit_element_old( pc, arrays, index );
	    }
	    break;
	}
	case GL_UNSIGNED_SHORT: {
	    const GLushort * us_ptr = (const GLushort *) indices;

	    for ( i = 0 ; i < elements_per_request ; i++ ) {
		const GLint index = (GLint) *(us_ptr++);
		pc = emit_element_old( pc, arrays, index );
	    }
	    break;
	}
	case GL_UNSIGNED_BYTE: {
	    const GLubyte  * ub_ptr = (const GLubyte  *) indices;

	    for ( i = 0 ; i < elements_per_request ; i++ ) {
		const GLint index = (GLint) *(ub_ptr++);
		pc = emit_element_old( pc, arrays, index );
	    }
	    break;
	}
	}

	if ( total_requests != 0 ) {
	    __glXSendLargeChunk( gc, req, total_requests, gc->pc,
				 pc - gc->pc );
	    pc = gc->pc;
	    req++;
	}

	count -= elements_per_request;
    }


    assert( (total_requests == 0) || ((req - 1) == total_requests) );

    if ( total_requests == 0 ) {
	assert( pc <= gc->bufEnd );

	gc->pc = pc;
	if ( gc->pc > gc->limit ) {
	    (void) __glXFlushRenderBuffer(gc, gc->pc);
	}
    }
}
Ejemplo n.º 4
0
/**
 * Emit the header data for the GL 1.1 / EXT_vertex_arrays DrawArrays
 * protocol.
 * 
 * \param gc                    GLX context.
 * \param arrays                Array state.
 * \param elements_per_request  Location to store the number of elements that
 *                              can fit in a single Render / RenderLarge
 *                              command.
 * \param total_request         Total number of requests for a RenderLarge
 *                              command.  If a Render command is used, this
 *                              will be zero.
 * \param mode                  Drawing mode.
 * \param count                 Number of vertices.
 * 
 * \returns
 * A pointer to the buffer for array data.
 */
static GLubyte *
emit_DrawArrays_header_old( __GLXcontext * gc,
			    struct array_state_vector * arrays,
			    size_t * elements_per_request,
			    size_t * total_requests,
			    GLenum mode, GLsizei count )
{
    size_t command_size;
    size_t single_vertex_size;
    const unsigned header_size = 16;
    unsigned  i;
    GLubyte * pc;


    /* Determine the size of the whole command.  This includes the header,
     * the ARRAY_INFO data and the array data.  Once this size is calculated,
     * it will be known whether a Render or RenderLarge command is needed.
     */

    single_vertex_size = 0;
    for ( i = 0 ; i < arrays->num_arrays ; i++ ) {
	if ( arrays->arrays[i].enabled ) {
	    single_vertex_size += __GLX_PAD( arrays->arrays[i].element_size );
	}
    }

    command_size = arrays->array_info_cache_size + header_size 
      + (single_vertex_size * count);


    /* Write the header for either a Render command or a RenderLarge
     * command.  After the header is written, write the ARRAY_INFO data.
     */

    if ( command_size > gc->maxSmallRenderCommandSize ) {
	/* maxSize is the maximum amount of data can be stuffed into a single
	 * packet.  sz_xGLXRenderReq is added because bufSize is the maximum
	 * packet size minus sz_xGLXRenderReq.
	 */
	const size_t maxSize = (gc->bufSize + sz_xGLXRenderReq)
	  - sz_xGLXRenderLargeReq;
	unsigned vertex_requests;


	/* Calculate the number of data packets that will be required to send
	 * the whole command.  To do this, the number of verticies that
	 * will fit in a single buffer must be calculated.
	 * 
	 * The important value here is elements_per_request.  This is the
	 * number of complete array elements that will fit in a single
	 * buffer.  There may be some wasted space at the end of the buffer,
	 * but splitting elements across buffer boundries would be painful.
	 */

	elements_per_request[0] = maxSize / single_vertex_size;

	vertex_requests = (count + elements_per_request[0] - 1)
	  / elements_per_request[0];
	  
	*total_requests = vertex_requests + 1;


	__glXFlushRenderBuffer(gc, gc->pc);

	command_size += 4;

	pc = ((GLubyte *) arrays->array_info_cache) - (header_size + 4);
	*(uint32_t *)(pc +  0) = command_size;
	*(uint32_t *)(pc +  4) = X_GLrop_DrawArrays;
	*(uint32_t *)(pc +  8) = count;
	*(uint32_t *)(pc + 12) = arrays->enabled_client_array_count;
	*(uint32_t *)(pc + 16) = mode;

	__glXSendLargeChunk( gc, 1, *total_requests, pc,
			     header_size + 4 + arrays->array_info_cache_size );

	pc = gc->pc;
    }
    else {
	if ( (gc->pc + command_size) >= gc->bufEnd ) {
	    (void) __glXFlushRenderBuffer(gc, gc->pc);
	}

	pc = gc->pc;
	*(uint16_t *)(pc +  0) = command_size;
	*(uint16_t *)(pc +  2) = X_GLrop_DrawArrays;
	*(uint32_t *)(pc +  4) = count;
	*(uint32_t *)(pc +  8) = arrays->enabled_client_array_count;
	*(uint32_t *)(pc + 12) = mode;

	pc += header_size;

	(void) memcpy( pc, arrays->array_info_cache,
		       arrays->array_info_cache_size );
	pc += arrays->array_info_cache_size;

	*elements_per_request = count;
	*total_requests = 0;
    }


    return pc;
}
Ejemplo n.º 5
0
/**
 * Emit GLX DrawArrays protocol using a GLXRenderLarge packet.
 */
static void   
emit_RenderLarge_DrawArrays(__GLXcontext * gc, const struct array_info * arrays,
		       GLsizei first, GLsizei count, GLsizei num_arrays, GLenum mode,
		       GLsizei cmdlen, GLsizei total_vertex_size)
{
    GLubyte * pc = gc->pc;
    GLsizei offset;
    GLsizei i;
    GLint maxSize;
    GLint totalRequests;
    GLint requestNumber;
    GLsizei elements_per_request;


    /* Calculate the maximum amount of data can be stuffed into a single
     * packet.  sz_xGLXRenderReq is added because bufSize is the maximum
     * packet size minus sz_xGLXRenderReq.
     * 
     * The important value here is elements_per_request.  This is the number
     * of complete array elements that will fit in a single buffer.  There
     * may be some wasted space at the end of the buffer, but splitting
     * elements across buffer boundries would be painful.
     */

    maxSize = (gc->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;

    elements_per_request = maxSize / total_vertex_size;

    totalRequests = ((count + (elements_per_request - 1))
		     / elements_per_request) + 1;


    /* Fill in the header data and send it away.
     */

    __GLX_BEGIN_VARIABLE_LARGE(X_GLrop_DrawArrays, cmdlen+4);
    emit_header(pc + 8, arrays, num_arrays, count, mode);

    gc->pc = pc + (__GLX_DRAWARRAYS_CMD_HDR_SIZE + 4)
	    + (__GLX_COMPONENT_HDR_SIZE * num_arrays);
    __glXSendLargeChunk(gc, 1, totalRequests, gc->buf, gc->pc - gc->buf);


    /* Write the actual array data.
     */
    offset = 0;
    requestNumber = 2;
    for ( i = 0 ; i < count ; i++ ) {
	if ( i == elements_per_request ) {
	    __glXSendLargeChunk(gc, requestNumber, totalRequests, 
				gc->buf, offset);
	    requestNumber++;
	    offset = 0;

	    count -= i;
	    first += i;
	    i = 0;
	}

	offset = emit_vertex(gc->buf, arrays, num_arrays, i + first, offset);
    }

    /* If the buffer isn't empty, emit the last, partial request.
     */
    if ( offset != 0 ) {
	assert(requestNumber == totalRequests);
	__glXSendLargeChunk(gc, requestNumber, totalRequests, gc->buf, offset);
    }

    gc->pc = gc->buf;
}