📄 intel_batchbuffer.c
字号:
/************************************************************************** * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/#include <stdio.h>#include <errno.h>#include "mtypes.h"#include "context.h"#include "enums.h"#include "vblank.h"#include "intel_reg.h"#include "intel_batchbuffer.h"#include "intel_context.h"/* ================================================================ * Performance monitoring functions */static void intel_fill_box( intelContextPtr intel, GLshort x, GLshort y, GLshort w, GLshort h, GLubyte r, GLubyte g, GLubyte b ){ x += intel->drawX; y += intel->drawY; if (x >= 0 && y >= 0 && x+w < intel->intelScreen->width && y+h < intel->intelScreen->height) intelEmitFillBlitLocked( intel, intel->intelScreen->cpp, intel->intelScreen->back.pitch, intel->intelScreen->back.offset, x, y, w, h, INTEL_PACKCOLOR(intel->intelScreen->fbFormat, r,g,b,0xff));}static void intel_draw_performance_boxes( intelContextPtr intel ){ /* Purple box for page flipping */ if ( intel->perf_boxes & I830_BOX_FLIP ) intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 ); /* Red box if we have to wait for idle at any point */ if ( intel->perf_boxes & I830_BOX_WAIT ) intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 ); /* Blue box: lost context? */ if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT ) intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 ); /* Yellow box for texture swaps */ if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD ) intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 ); /* Green box if hardware never idles (as far as we can tell) */ if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) ) intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 ); /* Draw bars indicating number of buffers allocated * (not a great measure, easily confused) */#if 0 if (intel->dma_used) { int bar = intel->dma_used / 10240; if (bar > 100) bar = 100; if (bar < 1) bar = 1; intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 ); intel->dma_used = 0; }#endif intel->perf_boxes = 0;}static int bad_prim_vertex_nr( int primitive, int nr ){ switch (primitive & PRIM3D_MASK) { case PRIM3D_POINTLIST: return nr < 1; case PRIM3D_LINELIST: return (nr & 1) || nr == 0; case PRIM3D_LINESTRIP: return nr < 2; case PRIM3D_TRILIST: case PRIM3D_RECTLIST: return nr % 3 || nr == 0; case PRIM3D_POLY: case PRIM3D_TRIFAN: case PRIM3D_TRISTRIP: case PRIM3D_TRISTRIP_RVRSE: return nr < 3; default: return 1; } }static void intel_flush_inline_primitive( GLcontext *ctx ){ intelContextPtr intel = INTEL_CONTEXT( ctx ); GLuint used = intel->batch.ptr - intel->prim.start_ptr; GLuint vertcount; assert(intel->prim.primitive != ~0); if (1) { /* Check vertex size against the vertex we're specifying to * hardware. If it's wrong, ditch the primitive. */ if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size )) goto do_discard; vertcount = (used - 4)/ (intel->vertex_size * 4); if (!vertcount) goto do_discard; if (vertcount * intel->vertex_size * 4 != used - 4) { fprintf(stderr, "vertex size confusion %d %d\n", used, intel->vertex_size * vertcount * 4); goto do_discard; } if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) { fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive, vertcount); goto do_discard; } } if (used < 8) goto do_discard; *(int *)intel->prim.start_ptr = (_3DPRIMITIVE | intel->prim.primitive | (used/4-2)); goto finished; do_discard: intel->batch.ptr -= used; intel->batch.space += used; assert(intel->batch.space >= 0); finished: intel->prim.primitive = ~0; intel->prim.start_ptr = 0; intel->prim.flush = 0;}/* Emit a primitive referencing vertices in a vertex buffer. */void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ){ BATCH_LOCALS; if (0) fprintf(stderr, "%s %x\n", __FUNCTION__, prim); /* Finish any in-progress primitive: */ INTEL_FIREVERTICES( intel ); /* Emit outstanding state: */ intel->vtbl.emit_state( intel ); /* Make sure there is some space in this buffer: */ if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space) { intelFlushBatch(intel, GL_TRUE); intel->vtbl.emit_state( intel ); }#if 1 if (((int)intel->batch.ptr) & 0x4) { BEGIN_BATCH(1); OUT_BATCH(0); ADVANCE_BATCH(); }#endif /* Emit a slot which will be filled with the inline primitive * command later. */ BEGIN_BATCH(2); OUT_BATCH( 0 ); intel->prim.start_ptr = batch_ptr; intel->prim.primitive = prim; intel->prim.flush = intel_flush_inline_primitive; intel->batch.contains_geometry = 1; OUT_BATCH( 0 ); ADVANCE_BATCH();}void intelRestartInlinePrimitive( intelContextPtr intel ){ GLuint prim = intel->prim.primitive; intel_flush_inline_primitive( &intel->ctx ); if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */ intelStartInlinePrimitive( intel, prim );}void intelWrapInlinePrimitive( intelContextPtr intel ){ GLuint prim = intel->prim.primitive; if (0) fprintf(stderr, "%s\n", __FUNCTION__); intel_flush_inline_primitive( &intel->ctx ); intelFlushBatch(intel, GL_TRUE); intelStartInlinePrimitive( intel, prim );}/* Emit a primitive with space for inline vertices. */GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel, int primitive, int dwords, int vertex_size ){ GLuint *tmp = 0; BATCH_LOCALS; if (0) fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords); /* Emit outstanding state: */ intel->vtbl.emit_state( intel ); if ((1+dwords)*4 >= intel->batch.space) { intelFlushBatch(intel, GL_TRUE); intel->vtbl.emit_state( intel ); } if (1) { int used = dwords * 4; int vertcount; /* Check vertex size against the vertex we're specifying to * hardware. If it's wrong, ditch the primitive. */ if (!intel->vtbl.check_vertex_size( intel, vertex_size )) goto do_discard; vertcount = dwords / vertex_size; if (dwords % vertex_size) { fprintf(stderr, "did not request a whole number of vertices\n"); goto do_discard; } if (bad_prim_vertex_nr( primitive, vertcount )) { fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount); goto do_discard; } if (used < 8) goto do_discard; } /* Emit 3D_PRIMITIVE commands: */ BEGIN_BATCH(1 + dwords); OUT_BATCH( _3DPRIMITIVE | primitive | (dwords-1) ); tmp = (GLuint *)batch_ptr; batch_ptr += dwords * 4; ADVANCE_BATCH(); intel->batch.contains_geometry = 1; do_discard: return tmp;}static void intelWaitForFrameCompletion( intelContextPtr intel ){ drm_i915_sarea_t *sarea = (drm_i915_sarea_t *)intel->sarea; if (intel->do_irqs) { if (intelGetLastFrame(intel) < sarea->last_dispatch) { if (!intel->irqsEmitted) { while (intelGetLastFrame (intel) < sarea->last_dispatch) ; } else { UNLOCK_HARDWARE( intel ); intelWaitIrq( intel, intel->alloc.irq_emitted ); LOCK_HARDWARE( intel ); } intel->irqsEmitted = 10; } if (intel->irqsEmitted) { intelEmitIrqLocked( intel ); intel->irqsEmitted--; } } else { while (intelGetLastFrame (intel) < sarea->last_dispatch) { UNLOCK_HARDWARE( intel ); if (intel->do_usleeps) DO_USLEEP( 1 ); LOCK_HARDWARE( intel ); } }}/* * Copy the back buffer to the front buffer. */void intelCopyBuffer( const __DRIdrawablePrivate *dPriv, const drm_clip_rect_t *rect){ intelContextPtr intel; GLboolean missed_target; int64_t ust; if (0) fprintf(stderr, "%s\n", __FUNCTION__); assert(dPriv); assert(dPriv->driContextPriv); assert(dPriv->driContextPriv->driverPrivate); intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate; intelFlush( &intel->ctx ); LOCK_HARDWARE( intel ); intelWaitForFrameCompletion( intel ); if (!rect) { UNLOCK_HARDWARE( intel ); driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target ); LOCK_HARDWARE( intel ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -