Merge branch 'i965g-restart'
Conflicts: configure.ac
This commit is contained in:
@@ -70,6 +70,7 @@
|
||||
#include "util/u_stream.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_tile.h"
|
||||
#include "util/u_prim.h"
|
||||
|
||||
|
||||
#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
|
||||
@@ -601,6 +602,32 @@ const char *pf_name( enum pipe_format format )
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const struct debug_named_value pipe_prim_names[] = {
|
||||
#ifdef DEBUG
|
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_POINTS),
|
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_LINES),
|
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_LOOP),
|
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP),
|
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES),
|
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP),
|
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_FAN),
|
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_QUADS),
|
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_QUAD_STRIP),
|
||||
DEBUG_NAMED_VALUE(PIPE_PRIM_POLYGON),
|
||||
#endif
|
||||
DEBUG_NAMED_VALUE_END
|
||||
};
|
||||
|
||||
|
||||
const char *u_prim_name( unsigned prim )
|
||||
{
|
||||
return debug_dump_enum(pipe_prim_names, prim);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void debug_dump_image(const char *prefix,
|
||||
unsigned format, unsigned cpp,
|
||||
|
||||
@@ -583,6 +583,19 @@ do { \
|
||||
#endif
|
||||
|
||||
|
||||
static INLINE uint32_t util_unsigned_fixed(float value, unsigned frac_bits)
|
||||
{
|
||||
value *= (1<<frac_bits);
|
||||
return value < 0 ? 0 : value;
|
||||
}
|
||||
|
||||
static INLINE int32_t util_signed_fixed(float value, unsigned frac_bits)
|
||||
{
|
||||
return value * (1<<frac_bits);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -135,4 +135,6 @@ static INLINE unsigned u_reduced_prim( unsigned pipe_prim )
|
||||
}
|
||||
}
|
||||
|
||||
const char *u_prim_name( unsigned pipe_prim );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#ifndef U_UPLOAD_MGR_H
|
||||
#define U_UPLOAD_MGR_H
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
struct pipe_screen;
|
||||
struct pipe_buffer;
|
||||
struct u_upload_mgr;
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
TOP = ../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
LIBNAME = i965
|
||||
|
||||
C_SOURCES = \
|
||||
brw_cc.c \
|
||||
brw_clip.c \
|
||||
brw_clip_line.c \
|
||||
brw_clip_point.c \
|
||||
brw_clip_state.c \
|
||||
brw_clip_tri.c \
|
||||
brw_clip_unfilled.c \
|
||||
brw_clip_util.c \
|
||||
brw_context.c \
|
||||
brw_curbe.c \
|
||||
brw_disasm.c \
|
||||
brw_draw.c \
|
||||
brw_draw_upload.c \
|
||||
brw_eu.c \
|
||||
brw_eu_debug.c \
|
||||
brw_eu_emit.c \
|
||||
brw_eu_util.c \
|
||||
brw_gs.c \
|
||||
brw_gs_emit.c \
|
||||
brw_gs_state.c \
|
||||
brw_misc_state.c \
|
||||
brw_pipe_blend.c \
|
||||
brw_pipe_depth.c \
|
||||
brw_pipe_fb.c \
|
||||
brw_pipe_query.c \
|
||||
brw_pipe_shader.c \
|
||||
brw_pipe_flush.c \
|
||||
brw_pipe_misc.c \
|
||||
brw_pipe_sampler.c \
|
||||
brw_pipe_vertex.c \
|
||||
brw_pipe_clear.c \
|
||||
brw_pipe_rast.c \
|
||||
brw_sf.c \
|
||||
brw_sf_emit.c \
|
||||
brw_sf_state.c \
|
||||
brw_state_batch.c \
|
||||
brw_state_debug.c \
|
||||
brw_state_cache.c \
|
||||
brw_state_upload.c \
|
||||
brw_structs_dump.c \
|
||||
brw_swtnl.c \
|
||||
brw_urb.c \
|
||||
brw_util.c \
|
||||
brw_vs.c \
|
||||
brw_vs_emit.c \
|
||||
brw_vs_state.c \
|
||||
brw_vs_surface_state.c \
|
||||
brw_wm.c \
|
||||
brw_wm_debug.c \
|
||||
brw_wm_emit.c \
|
||||
brw_wm_fp.c \
|
||||
brw_wm_iz.c \
|
||||
brw_wm_pass0.c \
|
||||
brw_wm_pass1.c \
|
||||
brw_wm_pass2.c \
|
||||
brw_wm_sampler_state.c \
|
||||
brw_wm_state.c \
|
||||
brw_wm_surface_state.c \
|
||||
brw_screen.c \
|
||||
brw_screen_buffers.c \
|
||||
brw_screen_tex_layout.c \
|
||||
brw_screen_texture.c \
|
||||
brw_screen_surface.c \
|
||||
brw_batchbuffer.c \
|
||||
brw_winsys_debug.c \
|
||||
intel_decode.c
|
||||
|
||||
include ../../Makefile.template
|
||||
@@ -0,0 +1,77 @@
|
||||
Import('*')
|
||||
|
||||
env = env.Clone()
|
||||
|
||||
i965 = env.ConvenienceLibrary(
|
||||
target = 'i965',
|
||||
source = [
|
||||
'brw_batchbuffer.c',
|
||||
'brw_cc.c',
|
||||
'brw_clip.c',
|
||||
'brw_clip_line.c',
|
||||
'brw_clip_point.c',
|
||||
'brw_clip_state.c',
|
||||
'brw_clip_tri.c',
|
||||
'brw_clip_unfilled.c',
|
||||
'brw_clip_util.c',
|
||||
'brw_context.c',
|
||||
'brw_curbe.c',
|
||||
'brw_disasm.c',
|
||||
'brw_draw.c',
|
||||
'brw_draw_upload.c',
|
||||
'brw_eu.c',
|
||||
'brw_eu_debug.c',
|
||||
'brw_eu_emit.c',
|
||||
'brw_eu_util.c',
|
||||
'brw_gs.c',
|
||||
'brw_gs_emit.c',
|
||||
'brw_gs_state.c',
|
||||
'brw_misc_state.c',
|
||||
'brw_pipe_blend.c',
|
||||
'brw_pipe_clear.c',
|
||||
'brw_pipe_depth.c',
|
||||
'brw_pipe_fb.c',
|
||||
'brw_pipe_flush.c',
|
||||
'brw_pipe_misc.c',
|
||||
'brw_pipe_query.c',
|
||||
'brw_pipe_rast.c',
|
||||
'brw_pipe_sampler.c',
|
||||
'brw_pipe_shader.c',
|
||||
'brw_pipe_vertex.c',
|
||||
'brw_screen_buffers.c',
|
||||
'brw_screen.c',
|
||||
'brw_screen_surface.c',
|
||||
'brw_screen_tex_layout.c',
|
||||
'brw_screen_texture.c',
|
||||
'brw_structs_dump.c',
|
||||
'brw_sf.c',
|
||||
'brw_sf_emit.c',
|
||||
'brw_sf_state.c',
|
||||
'brw_state_batch.c',
|
||||
'brw_state_cache.c',
|
||||
# 'brw_state_debug.c',
|
||||
'brw_state_upload.c',
|
||||
'brw_swtnl.c',
|
||||
'brw_urb.c',
|
||||
'brw_util.c',
|
||||
'brw_vs.c',
|
||||
'brw_vs_emit.c',
|
||||
'brw_vs_state.c',
|
||||
'brw_vs_surface_state.c',
|
||||
'brw_wm.c',
|
||||
# 'brw_wm_constant_buffer.c',
|
||||
'brw_wm_debug.c',
|
||||
'brw_wm_emit.c',
|
||||
'brw_wm_fp.c',
|
||||
# 'brw_wm_glsl.c',
|
||||
'brw_wm_iz.c',
|
||||
'brw_wm_pass0.c',
|
||||
'brw_wm_pass1.c',
|
||||
'brw_wm_pass2.c',
|
||||
'brw_wm_sampler_state.c',
|
||||
'brw_wm_state.c',
|
||||
'brw_wm_surface_state.c',
|
||||
'intel_decode.c',
|
||||
])
|
||||
|
||||
Export('i965')
|
||||
@@ -0,0 +1,202 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 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 "util/u_memory.h"
|
||||
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_reg.h"
|
||||
#include "brw_winsys.h"
|
||||
#include "brw_debug.h"
|
||||
#include "brw_structs.h"
|
||||
|
||||
#define ALWAYS_EMIT_MI_FLUSH 1
|
||||
|
||||
enum pipe_error
|
||||
brw_batchbuffer_reset(struct brw_batchbuffer *batch)
|
||||
{
|
||||
enum pipe_error ret;
|
||||
|
||||
ret = batch->sws->bo_alloc( batch->sws,
|
||||
BRW_BUFFER_TYPE_BATCH,
|
||||
BRW_BATCH_SIZE, 4096,
|
||||
&batch->buf );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
batch->size = BRW_BATCH_SIZE;
|
||||
|
||||
/* With map_range semantics, the winsys can decide whether to
|
||||
* inject a malloc'ed bounce buffer instead of mapping directly.
|
||||
*/
|
||||
batch->map = batch->sws->bo_map(batch->buf,
|
||||
BRW_DATA_BATCH_BUFFER,
|
||||
0, batch->size,
|
||||
GL_TRUE,
|
||||
GL_TRUE,
|
||||
GL_TRUE);
|
||||
|
||||
batch->ptr = batch->map;
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
struct brw_batchbuffer *
|
||||
brw_batchbuffer_alloc(struct brw_winsys_screen *sws,
|
||||
struct brw_chipset chipset)
|
||||
{
|
||||
struct brw_batchbuffer *batch = CALLOC_STRUCT(brw_batchbuffer);
|
||||
|
||||
batch->sws = sws;
|
||||
batch->chipset = chipset;
|
||||
brw_batchbuffer_reset(batch);
|
||||
|
||||
return batch;
|
||||
}
|
||||
|
||||
void
|
||||
brw_batchbuffer_free(struct brw_batchbuffer *batch)
|
||||
{
|
||||
if (batch->map) {
|
||||
batch->sws->bo_unmap(batch->buf);
|
||||
batch->map = NULL;
|
||||
}
|
||||
|
||||
bo_reference(&batch->buf, NULL);
|
||||
FREE(batch);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_brw_batchbuffer_flush(struct brw_batchbuffer *batch,
|
||||
const char *file,
|
||||
int line)
|
||||
{
|
||||
GLuint used = batch->ptr - batch->map;
|
||||
|
||||
if (used == 0)
|
||||
return;
|
||||
|
||||
/* Post-swap throttling done by the state tracker.
|
||||
*/
|
||||
|
||||
if (BRW_DEBUG & DEBUG_BATCH)
|
||||
debug_printf("%s:%d: Batchbuffer flush with %db used\n",
|
||||
file, line, used);
|
||||
|
||||
if (ALWAYS_EMIT_MI_FLUSH) {
|
||||
*(GLuint *) (batch->ptr) = MI_FLUSH | BRW_FLUSH_STATE_CACHE;
|
||||
batch->ptr += 4;
|
||||
used = batch->ptr - batch->map;
|
||||
}
|
||||
|
||||
/* Round batchbuffer usage to 2 DWORDs.
|
||||
*/
|
||||
if ((used & 4) == 0) {
|
||||
*(GLuint *) (batch->ptr) = 0; /* noop */
|
||||
batch->ptr += 4;
|
||||
used = batch->ptr - batch->map;
|
||||
}
|
||||
|
||||
/* Mark the end of the buffer.
|
||||
*/
|
||||
*(GLuint *) (batch->ptr) = MI_BATCH_BUFFER_END;
|
||||
batch->ptr += 4;
|
||||
used = batch->ptr - batch->map;
|
||||
|
||||
batch->sws->bo_flush_range(batch->buf, 0, used);
|
||||
batch->sws->bo_unmap(batch->buf);
|
||||
batch->map = NULL;
|
||||
batch->ptr = NULL;
|
||||
|
||||
batch->sws->bo_exec(batch->buf, used );
|
||||
|
||||
if (BRW_DEBUG & DEBUG_SYNC) {
|
||||
/* Abuse map/unmap to achieve wait-for-fence.
|
||||
*
|
||||
* XXX: hide this inside the winsys and export a fence
|
||||
* interface.
|
||||
*/
|
||||
debug_printf("waiting for idle\n");
|
||||
batch->sws->bo_wait_idle(batch->buf);
|
||||
}
|
||||
|
||||
/* Reset the buffer:
|
||||
*/
|
||||
brw_batchbuffer_reset(batch);
|
||||
}
|
||||
|
||||
|
||||
/* The OUT_RELOC() macro ends up here, generating a relocation within
|
||||
* the batch buffer.
|
||||
*/
|
||||
enum pipe_error
|
||||
brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch,
|
||||
struct brw_winsys_buffer *buffer,
|
||||
uint32_t usage,
|
||||
uint32_t delta)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (batch->ptr - batch->map > batch->buf->size) {
|
||||
debug_printf("bad relocation ptr %p map %p offset %d size %d\n",
|
||||
batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size);
|
||||
|
||||
return PIPE_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
ret = batch->sws->bo_emit_reloc(batch->buf,
|
||||
usage,
|
||||
delta,
|
||||
batch->ptr - batch->map,
|
||||
buffer);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* bo_emit_reloc was resposible for writing a zero into the
|
||||
* batchbuffer if necessary. Just need to update our pointer.
|
||||
*/
|
||||
batch->ptr += 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum pipe_error
|
||||
brw_batchbuffer_data(struct brw_batchbuffer *batch,
|
||||
const void *data, GLuint bytes,
|
||||
enum cliprect_mode cliprect_mode)
|
||||
{
|
||||
enum pipe_error ret;
|
||||
|
||||
assert((bytes & 3) == 0);
|
||||
|
||||
ret = brw_batchbuffer_require_space(batch, bytes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(batch->ptr, data, bytes);
|
||||
batch->ptr += bytes;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#ifndef BRW_BATCHBUFFER_H
|
||||
#define BRW_BATCHBUFFER_H
|
||||
|
||||
#include "util/u_debug.h"
|
||||
|
||||
#include "brw_types.h"
|
||||
#include "brw_winsys.h"
|
||||
#include "brw_reg.h"
|
||||
|
||||
#define BATCH_SZ 16384
|
||||
#define BATCH_RESERVED 16
|
||||
|
||||
/* All ignored:
|
||||
*/
|
||||
enum cliprect_mode {
|
||||
IGNORE_CLIPRECTS,
|
||||
LOOP_CLIPRECTS,
|
||||
NO_LOOP_CLIPRECTS,
|
||||
REFERENCES_CLIPRECTS
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
struct brw_batchbuffer {
|
||||
|
||||
struct brw_winsys_screen *sws;
|
||||
struct brw_winsys_buffer *buf;
|
||||
struct brw_chipset chipset;
|
||||
|
||||
/**
|
||||
* Values exported to speed up the writing the batchbuffer,
|
||||
* instead of having to go trough a accesor function for
|
||||
* each dword written.
|
||||
*/
|
||||
/*{@*/
|
||||
uint8_t *map;
|
||||
uint8_t *ptr;
|
||||
size_t size;
|
||||
struct {
|
||||
uint8_t *end_ptr;
|
||||
} emit;
|
||||
|
||||
|
||||
size_t relocs;
|
||||
size_t max_relocs;
|
||||
/*@}*/
|
||||
};
|
||||
|
||||
struct brw_batchbuffer *brw_batchbuffer_alloc( struct brw_winsys_screen *sws,
|
||||
struct brw_chipset chipset );
|
||||
|
||||
void brw_batchbuffer_free(struct brw_batchbuffer *batch);
|
||||
|
||||
void _brw_batchbuffer_flush(struct brw_batchbuffer *batch,
|
||||
const char *file, int line);
|
||||
|
||||
|
||||
enum pipe_error
|
||||
brw_batchbuffer_reset(struct brw_batchbuffer *batch);
|
||||
|
||||
|
||||
/* Unlike bmBufferData, this currently requires the buffer be mapped.
|
||||
* Consider it a convenience function wrapping multple
|
||||
* intel_buffer_dword() calls.
|
||||
*/
|
||||
int brw_batchbuffer_data(struct brw_batchbuffer *batch,
|
||||
const void *data, GLuint bytes,
|
||||
enum cliprect_mode cliprect_mode);
|
||||
|
||||
|
||||
int brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch,
|
||||
struct brw_winsys_buffer *buffer,
|
||||
enum brw_buffer_usage usage,
|
||||
uint32_t offset);
|
||||
|
||||
/* Inline functions - might actually be better off with these
|
||||
* non-inlined. Certainly better off switching all command packets to
|
||||
* be passed as structs rather than dwords, but that's a little bit of
|
||||
* work...
|
||||
*/
|
||||
static INLINE GLint
|
||||
brw_batchbuffer_space(struct brw_batchbuffer *batch)
|
||||
{
|
||||
return (batch->size - BATCH_RESERVED) - (batch->ptr - batch->map);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
brw_batchbuffer_emit_dword(struct brw_batchbuffer *batch, GLuint dword)
|
||||
{
|
||||
assert(batch->map);
|
||||
assert(brw_batchbuffer_space(batch) >= 4);
|
||||
*(GLuint *) (batch->ptr) = dword;
|
||||
batch->ptr += 4;
|
||||
}
|
||||
|
||||
static INLINE enum pipe_error
|
||||
brw_batchbuffer_require_space(struct brw_batchbuffer *batch,
|
||||
GLuint sz)
|
||||
{
|
||||
assert(sz < batch->size - 8);
|
||||
if (brw_batchbuffer_space(batch) < sz) {
|
||||
assert(0);
|
||||
return PIPE_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
batch->emit.end_ptr = batch->ptr + sz;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Here are the crusty old macros, to be removed:
|
||||
*/
|
||||
#define BEGIN_BATCH(n, cliprect_mode) do { \
|
||||
brw_batchbuffer_require_space(brw->batch, (n)*4); \
|
||||
} while (0)
|
||||
|
||||
#define OUT_BATCH(d) brw_batchbuffer_emit_dword(brw->batch, d)
|
||||
|
||||
#define OUT_RELOC(buf, usage, delta) do { \
|
||||
assert((unsigned) (delta) < buf->size); \
|
||||
brw_batchbuffer_emit_reloc(brw->batch, buf, \
|
||||
usage, delta); \
|
||||
} while (0)
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ADVANCE_BATCH() do { \
|
||||
unsigned int _n = brw->batch->ptr - brw->batch->emit.end_ptr; \
|
||||
if (_n != 0) { \
|
||||
debug_printf("%s: %d too many bytes emitted to batch\n", \
|
||||
__FUNCTION__, _n); \
|
||||
abort(); \
|
||||
} \
|
||||
brw->batch->emit.end_ptr = NULL; \
|
||||
} while(0)
|
||||
#else
|
||||
#define ADVANCE_BATCH()
|
||||
#endif
|
||||
|
||||
static INLINE void
|
||||
brw_batchbuffer_emit_mi_flush(struct brw_batchbuffer *batch)
|
||||
{
|
||||
brw_batchbuffer_require_space(batch, 4);
|
||||
brw_batchbuffer_emit_dword(batch, MI_FLUSH);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_defines.h"
|
||||
|
||||
|
||||
static enum pipe_error prepare_cc_vp( struct brw_context *brw )
|
||||
{
|
||||
return brw_cache_data( &brw->cache,
|
||||
BRW_CC_VP,
|
||||
&brw->curr.ccv,
|
||||
NULL, 0,
|
||||
&brw->cc.reloc[CC_RELOC_VP].bo );
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_cc_vp = {
|
||||
.dirty = {
|
||||
.mesa = PIPE_NEW_VIEWPORT,
|
||||
.brw = BRW_NEW_CONTEXT,
|
||||
.cache = 0
|
||||
},
|
||||
.prepare = prepare_cc_vp
|
||||
};
|
||||
|
||||
|
||||
/* A long-winded way to OR two unsigned integers together:
|
||||
*/
|
||||
static INLINE struct brw_cc3
|
||||
combine_cc3( struct brw_cc3 a, struct brw_cc3 b )
|
||||
{
|
||||
union { struct brw_cc3 cc3; unsigned i; } ca, cb;
|
||||
ca.cc3 = a;
|
||||
cb.cc3 = b;
|
||||
ca.i |= cb.i;
|
||||
return ca.cc3;
|
||||
}
|
||||
|
||||
|
||||
static int prepare_cc_unit( struct brw_context *brw )
|
||||
{
|
||||
brw->cc.cc.cc0 = brw->curr.zstencil->cc0;
|
||||
brw->cc.cc.cc1 = brw->curr.zstencil->cc1;
|
||||
brw->cc.cc.cc2 = brw->curr.zstencil->cc2;
|
||||
brw->cc.cc.cc3 = combine_cc3( brw->curr.zstencil->cc3, brw->curr.blend->cc3 );
|
||||
|
||||
brw->cc.cc.cc5 = brw->curr.blend->cc5;
|
||||
brw->cc.cc.cc6 = brw->curr.blend->cc6;
|
||||
brw->cc.cc.cc7 = brw->curr.zstencil->cc7;
|
||||
|
||||
return brw_cache_data_sz(&brw->cache, BRW_CC_UNIT,
|
||||
&brw->cc.cc, sizeof(brw->cc.cc),
|
||||
brw->cc.reloc, 1,
|
||||
&brw->cc.state_bo);
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_cc_unit = {
|
||||
.dirty = {
|
||||
.mesa = PIPE_NEW_DEPTH_STENCIL_ALPHA | PIPE_NEW_BLEND,
|
||||
.brw = 0,
|
||||
.cache = CACHE_NEW_CC_VP
|
||||
},
|
||||
.prepare = prepare_cc_unit,
|
||||
};
|
||||
|
||||
|
||||
void brw_hw_cc_init( struct brw_context *brw )
|
||||
{
|
||||
make_reloc(&brw->cc.reloc[0],
|
||||
BRW_USAGE_STATE,
|
||||
0,
|
||||
offsetof(struct brw_cc_unit_state, cc4),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
void brw_hw_cc_cleanup( struct brw_context *brw )
|
||||
{
|
||||
bo_reference(&brw->cc.state_bo, NULL);
|
||||
bo_reference(&brw->cc.reloc[0].bo, NULL);
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "brw_screen.h"
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_eu.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_pipe_rast.h"
|
||||
#include "brw_clip.h"
|
||||
|
||||
|
||||
#define FRONT_UNFILLED_BIT 0x1
|
||||
#define BACK_UNFILLED_BIT 0x2
|
||||
|
||||
|
||||
static enum pipe_error
|
||||
compile_clip_prog( struct brw_context *brw,
|
||||
struct brw_clip_prog_key *key,
|
||||
struct brw_winsys_buffer **bo_out )
|
||||
{
|
||||
enum pipe_error ret;
|
||||
struct brw_clip_compile c;
|
||||
const GLuint *program;
|
||||
GLuint program_size;
|
||||
GLuint delta;
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
/* Begin the compilation:
|
||||
*/
|
||||
brw_init_compile(brw, &c.func);
|
||||
|
||||
c.func.single_program_flow = 1;
|
||||
|
||||
c.chipset = brw->chipset;
|
||||
c.key = *key;
|
||||
c.need_ff_sync = c.chipset.is_igdng;
|
||||
|
||||
/* Need to locate the two positions present in vertex + header.
|
||||
* These are currently hardcoded:
|
||||
*/
|
||||
c.header_position_offset = ATTR_SIZE;
|
||||
|
||||
if (c.chipset.is_igdng)
|
||||
delta = 3 * REG_SIZE;
|
||||
else
|
||||
delta = REG_SIZE;
|
||||
|
||||
c.offset_hpos = delta + c.key.output_hpos * ATTR_SIZE;
|
||||
|
||||
if (c.key.output_color0)
|
||||
c.offset_color0 = delta + c.key.output_color0 * ATTR_SIZE;
|
||||
|
||||
if (c.key.output_color1)
|
||||
c.offset_color1 = delta + c.key.output_color1 * ATTR_SIZE;
|
||||
|
||||
if (c.key.output_bfc0)
|
||||
c.offset_bfc0 = delta + c.key.output_bfc0 * ATTR_SIZE;
|
||||
|
||||
if (c.key.output_bfc1)
|
||||
c.offset_bfc1 = delta + c.key.output_bfc1 * ATTR_SIZE;
|
||||
|
||||
if (c.key.output_edgeflag)
|
||||
c.offset_edgeflag = delta + c.key.output_edgeflag * ATTR_SIZE;
|
||||
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
c.nr_regs = (c.key.nr_attrs + 1) / 2 + 3; /* are vertices packed, or reg-aligned? */
|
||||
else
|
||||
c.nr_regs = (c.key.nr_attrs + 1) / 2 + 1; /* are vertices packed, or reg-aligned? */
|
||||
|
||||
c.nr_bytes = c.nr_regs * REG_SIZE;
|
||||
|
||||
c.prog_data.clip_mode = c.key.clip_mode; /* XXX */
|
||||
|
||||
/* For some reason the thread is spawned with only 4 channels
|
||||
* unmasked.
|
||||
*/
|
||||
brw_set_mask_control(&c.func, BRW_MASK_DISABLE);
|
||||
|
||||
|
||||
/* Would ideally have the option of producing a program which could
|
||||
* do all three:
|
||||
*/
|
||||
switch (key->primitive) {
|
||||
case PIPE_PRIM_TRIANGLES:
|
||||
if (key->do_unfilled)
|
||||
brw_emit_unfilled_clip( &c );
|
||||
else
|
||||
brw_emit_tri_clip( &c );
|
||||
break;
|
||||
case PIPE_PRIM_LINES:
|
||||
brw_emit_line_clip( &c );
|
||||
break;
|
||||
case PIPE_PRIM_POINTS:
|
||||
brw_emit_point_clip( &c );
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return PIPE_ERROR_BAD_INPUT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* get the program
|
||||
*/
|
||||
ret = brw_get_program(&c.func, &program, &program_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Upload
|
||||
*/
|
||||
ret = brw_upload_cache( &brw->cache,
|
||||
BRW_CLIP_PROG,
|
||||
&c.key, sizeof(c.key),
|
||||
NULL, 0,
|
||||
program, program_size,
|
||||
&c.prog_data,
|
||||
&brw->clip.prog_data,
|
||||
bo_out );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
/* Calculate interpolants for triangle and line rasterization.
|
||||
*/
|
||||
static enum pipe_error
|
||||
upload_clip_prog(struct brw_context *brw)
|
||||
{
|
||||
const struct brw_vertex_shader *vs = brw->curr.vertex_shader;
|
||||
struct brw_clip_prog_key key;
|
||||
enum pipe_error ret;
|
||||
|
||||
/* Populate the key, starting from the almost-complete version from
|
||||
* the rast state.
|
||||
*/
|
||||
|
||||
/* PIPE_NEW_RAST */
|
||||
key = brw->curr.rast->clip_key;
|
||||
|
||||
/* BRW_NEW_REDUCED_PRIMITIVE */
|
||||
key.primitive = brw->reduced_primitive;
|
||||
|
||||
/* XXX: if edgeflag is moved to a proper TGSI vs output, can remove
|
||||
* dependency on CACHE_NEW_VS_PROG
|
||||
*/
|
||||
/* CACHE_NEW_VS_PROG */
|
||||
key.nr_attrs = brw->vs.prog_data->nr_outputs;
|
||||
key.output_edgeflag = brw->vs.prog_data->output_edgeflag;
|
||||
|
||||
/* PIPE_NEW_VS */
|
||||
key.output_hpos = vs->output_hpos;
|
||||
key.output_color0 = vs->output_color0;
|
||||
key.output_color1 = vs->output_color1;
|
||||
key.output_bfc0 = vs->output_bfc0;
|
||||
key.output_bfc1 = vs->output_bfc1;
|
||||
|
||||
/* PIPE_NEW_CLIP */
|
||||
key.nr_userclip = brw->curr.ucp.nr;
|
||||
|
||||
/* Already cached?
|
||||
*/
|
||||
if (brw_search_cache(&brw->cache, BRW_CLIP_PROG,
|
||||
&key, sizeof(key),
|
||||
NULL, 0,
|
||||
&brw->clip.prog_data,
|
||||
&brw->clip.prog_bo))
|
||||
return PIPE_OK;
|
||||
|
||||
/* Compile new program:
|
||||
*/
|
||||
ret = compile_clip_prog( brw, &key, &brw->clip.prog_bo );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
const struct brw_tracked_state brw_clip_prog = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_RAST |
|
||||
PIPE_NEW_CLIP),
|
||||
.brw = (BRW_NEW_REDUCED_PRIMITIVE),
|
||||
.cache = CACHE_NEW_VS_PROG
|
||||
},
|
||||
.prepare = upload_clip_prog
|
||||
};
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#ifndef BRW_CLIP_H
|
||||
#define BRW_CLIP_H
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
#include "brw_reg.h"
|
||||
#include "brw_eu.h"
|
||||
|
||||
#define MAX_VERTS (3+6+6)
|
||||
|
||||
/* Note that if unfilled primitives are being emitted, we have to fix
|
||||
* up polygon offset and flatshading at this point:
|
||||
*/
|
||||
struct brw_clip_prog_key {
|
||||
GLuint nr_attrs:6;
|
||||
GLuint primitive:4;
|
||||
GLuint nr_userclip:3;
|
||||
GLuint do_flat_shading:1;
|
||||
GLuint do_unfilled:1;
|
||||
GLuint fill_cw:2; /* includes cull information */
|
||||
GLuint fill_ccw:2; /* includes cull information */
|
||||
GLuint offset_cw:1;
|
||||
GLuint offset_ccw:1;
|
||||
GLuint copy_bfc_cw:1;
|
||||
GLuint copy_bfc_ccw:1;
|
||||
GLuint clip_mode:3;
|
||||
GLuint output_hpos:6; /* not always zero? */
|
||||
|
||||
GLuint output_color0:6;
|
||||
GLuint output_color1:6;
|
||||
GLuint output_bfc0:6;
|
||||
GLuint output_bfc1:6;
|
||||
GLuint output_edgeflag:6;
|
||||
GLuint pad1:2;
|
||||
|
||||
GLfloat offset_factor;
|
||||
GLfloat offset_units;
|
||||
};
|
||||
|
||||
struct brw_clip_prog_data {
|
||||
GLuint curb_read_length; /* user planes? */
|
||||
GLuint clip_mode;
|
||||
GLuint urb_read_length;
|
||||
GLuint total_grf;
|
||||
};
|
||||
|
||||
#define CLIP_LINE 0
|
||||
#define CLIP_POINT 1
|
||||
#define CLIP_FILL 2
|
||||
#define CLIP_CULL 3
|
||||
|
||||
|
||||
#define PRIM_MASK (0x1f)
|
||||
|
||||
struct brw_clip_compile {
|
||||
struct brw_compile func;
|
||||
struct brw_clip_prog_key key;
|
||||
struct brw_clip_prog_data prog_data;
|
||||
|
||||
struct {
|
||||
struct brw_reg R0;
|
||||
struct brw_reg vertex[MAX_VERTS];
|
||||
|
||||
struct brw_reg t;
|
||||
struct brw_reg t0, t1;
|
||||
struct brw_reg dp0, dp1;
|
||||
|
||||
struct brw_reg dpPrev;
|
||||
struct brw_reg dp;
|
||||
struct brw_reg loopcount;
|
||||
struct brw_reg nr_verts;
|
||||
struct brw_reg planemask;
|
||||
|
||||
struct brw_reg inlist;
|
||||
struct brw_reg outlist;
|
||||
struct brw_reg freelist;
|
||||
|
||||
struct brw_reg dir;
|
||||
struct brw_reg tmp0, tmp1;
|
||||
struct brw_reg offset;
|
||||
|
||||
struct brw_reg fixed_planes;
|
||||
struct brw_reg plane_equation;
|
||||
|
||||
struct brw_reg ff_sync;
|
||||
} reg;
|
||||
|
||||
/* 3 different ways of expressing vertex size, including
|
||||
* key.nr_attrs.
|
||||
*/
|
||||
GLuint nr_regs;
|
||||
GLuint nr_bytes;
|
||||
|
||||
GLuint first_tmp;
|
||||
GLuint last_tmp;
|
||||
|
||||
GLboolean need_direction;
|
||||
struct brw_chipset chipset;
|
||||
|
||||
GLuint last_mrf;
|
||||
|
||||
GLuint header_position_offset;
|
||||
GLboolean need_ff_sync;
|
||||
|
||||
GLuint nr_color_attrs;
|
||||
GLuint offset_color0;
|
||||
GLuint offset_color1;
|
||||
GLuint offset_bfc0;
|
||||
GLuint offset_bfc1;
|
||||
|
||||
GLuint offset_hpos;
|
||||
GLuint offset_edgeflag;
|
||||
};
|
||||
|
||||
#define ATTR_SIZE (4*4)
|
||||
|
||||
/* Points are only culled, so no need for a clip routine, however it
|
||||
* works out easier to have a dummy one.
|
||||
*/
|
||||
void brw_emit_unfilled_clip( struct brw_clip_compile *c );
|
||||
void brw_emit_tri_clip( struct brw_clip_compile *c );
|
||||
void brw_emit_line_clip( struct brw_clip_compile *c );
|
||||
void brw_emit_point_clip( struct brw_clip_compile *c );
|
||||
|
||||
/* brw_clip_tri.c, for use by the unfilled clip routine:
|
||||
*/
|
||||
void brw_clip_tri_init_vertices( struct brw_clip_compile *c );
|
||||
void brw_clip_tri_flat_shade( struct brw_clip_compile *c );
|
||||
void brw_clip_tri( struct brw_clip_compile *c );
|
||||
void brw_clip_tri_emit_polygon( struct brw_clip_compile *c );
|
||||
void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
|
||||
GLuint nr_verts );
|
||||
|
||||
|
||||
/* Utils:
|
||||
*/
|
||||
|
||||
void brw_clip_interp_vertex( struct brw_clip_compile *c,
|
||||
struct brw_indirect dest_ptr,
|
||||
struct brw_indirect v0_ptr, /* from */
|
||||
struct brw_indirect v1_ptr, /* to */
|
||||
struct brw_reg t0,
|
||||
GLboolean force_edgeflag );
|
||||
|
||||
void brw_clip_init_planes( struct brw_clip_compile *c );
|
||||
|
||||
void brw_clip_emit_vue(struct brw_clip_compile *c,
|
||||
struct brw_indirect vert,
|
||||
GLboolean allocate,
|
||||
GLboolean eot,
|
||||
GLuint header);
|
||||
|
||||
void brw_clip_kill_thread(struct brw_clip_compile *c);
|
||||
|
||||
struct brw_reg brw_clip_plane_stride( struct brw_clip_compile *c );
|
||||
struct brw_reg brw_clip_plane0_address( struct brw_clip_compile *c );
|
||||
|
||||
void brw_clip_copy_colors( struct brw_clip_compile *c,
|
||||
GLuint to, GLuint from );
|
||||
|
||||
void brw_clip_init_clipmask( struct brw_clip_compile *c );
|
||||
|
||||
struct brw_reg get_tmp( struct brw_clip_compile *c );
|
||||
|
||||
void brw_clip_project_position(struct brw_clip_compile *c,
|
||||
struct brw_reg pos );
|
||||
void brw_clip_ff_sync(struct brw_clip_compile *c);
|
||||
void brw_clip_init_ff_sync(struct brw_clip_compile *c);
|
||||
#endif
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_debug.h"
|
||||
|
||||
#include "brw_defines.h"
|
||||
#include "brw_eu.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_clip.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static void brw_clip_line_alloc_regs( struct brw_clip_compile *c )
|
||||
{
|
||||
GLuint i = 0,j;
|
||||
|
||||
/* Register usage is static, precompute here:
|
||||
*/
|
||||
c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
|
||||
|
||||
if (c->key.nr_userclip) {
|
||||
c->reg.fixed_planes = brw_vec4_grf(i, 0);
|
||||
i += (6 + c->key.nr_userclip + 1) / 2;
|
||||
|
||||
c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
|
||||
}
|
||||
else
|
||||
c->prog_data.curb_read_length = 0;
|
||||
|
||||
|
||||
/* Payload vertices plus space for more generated vertices:
|
||||
*/
|
||||
for (j = 0; j < 4; j++) {
|
||||
c->reg.vertex[j] = brw_vec4_grf(i, 0);
|
||||
i += c->nr_regs;
|
||||
}
|
||||
|
||||
c->reg.t = brw_vec1_grf(i, 0);
|
||||
c->reg.t0 = brw_vec1_grf(i, 1);
|
||||
c->reg.t1 = brw_vec1_grf(i, 2);
|
||||
c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
|
||||
c->reg.plane_equation = brw_vec4_grf(i, 4);
|
||||
i++;
|
||||
|
||||
c->reg.dp0 = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
|
||||
c->reg.dp1 = brw_vec1_grf(i, 4);
|
||||
i++;
|
||||
|
||||
if (!c->key.nr_userclip) {
|
||||
c->reg.fixed_planes = brw_vec8_grf(i, 0);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (c->need_ff_sync) {
|
||||
c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
|
||||
i++;
|
||||
}
|
||||
|
||||
c->first_tmp = i;
|
||||
c->last_tmp = i;
|
||||
|
||||
c->prog_data.urb_read_length = c->nr_regs; /* ? */
|
||||
c->prog_data.total_grf = i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Line clipping, more or less following the following algorithm:
|
||||
*
|
||||
* for (p=0;p<MAX_PLANES;p++) {
|
||||
* if (clipmask & (1 << p)) {
|
||||
* GLfloat dp0 = DOTPROD( vtx0, plane[p] );
|
||||
* GLfloat dp1 = DOTPROD( vtx1, plane[p] );
|
||||
*
|
||||
* if (IS_NEGATIVE(dp1)) {
|
||||
* GLfloat t = dp1 / (dp1 - dp0);
|
||||
* if (t > t1) t1 = t;
|
||||
* } else {
|
||||
* GLfloat t = dp0 / (dp0 - dp1);
|
||||
* if (t > t0) t0 = t;
|
||||
* }
|
||||
*
|
||||
* if (t0 + t1 >= 1.0)
|
||||
* return;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* interp( ctx, newvtx0, vtx0, vtx1, t0 );
|
||||
* interp( ctx, newvtx1, vtx1, vtx0, t1 );
|
||||
*
|
||||
*/
|
||||
static void clip_and_emit_line( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_indirect vtx0 = brw_indirect(0, 0);
|
||||
struct brw_indirect vtx1 = brw_indirect(1, 0);
|
||||
struct brw_indirect newvtx0 = brw_indirect(2, 0);
|
||||
struct brw_indirect newvtx1 = brw_indirect(3, 0);
|
||||
struct brw_indirect plane_ptr = brw_indirect(4, 0);
|
||||
struct brw_instruction *plane_loop;
|
||||
struct brw_instruction *plane_active;
|
||||
struct brw_instruction *is_negative;
|
||||
struct brw_instruction *is_neg2 = NULL;
|
||||
struct brw_instruction *not_culled;
|
||||
struct brw_reg v1_null_ud = retype(vec1(brw_null_reg()), BRW_REGISTER_TYPE_UD);
|
||||
|
||||
brw_MOV(p, get_addr_reg(vtx0), brw_address(c->reg.vertex[0]));
|
||||
brw_MOV(p, get_addr_reg(vtx1), brw_address(c->reg.vertex[1]));
|
||||
brw_MOV(p, get_addr_reg(newvtx0), brw_address(c->reg.vertex[2]));
|
||||
brw_MOV(p, get_addr_reg(newvtx1), brw_address(c->reg.vertex[3]));
|
||||
brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
|
||||
|
||||
/* Note: init t0, t1 together:
|
||||
*/
|
||||
brw_MOV(p, vec2(c->reg.t0), brw_imm_f(0));
|
||||
|
||||
brw_clip_init_planes(c);
|
||||
brw_clip_init_clipmask(c);
|
||||
|
||||
/* -ve rhw workaround */
|
||||
if (c->chipset.is_965) {
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
|
||||
brw_imm_ud(1<<20));
|
||||
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(0x3f));
|
||||
}
|
||||
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
|
||||
plane_loop = brw_DO(p, BRW_EXECUTE_1);
|
||||
{
|
||||
/* if (planemask & 1)
|
||||
*/
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_AND(p, v1_null_ud, c->reg.planemask, brw_imm_ud(1));
|
||||
|
||||
plane_active = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
if (c->key.nr_userclip)
|
||||
brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
|
||||
else
|
||||
brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
|
||||
|
||||
/* dp = DP4(vtx->position, plane)
|
||||
*/
|
||||
brw_DP4(p, vec4(c->reg.dp0), deref_4f(vtx0, c->offset_hpos), c->reg.plane_equation);
|
||||
|
||||
/* if (IS_NEGATIVE(dp1))
|
||||
*/
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
|
||||
brw_DP4(p, vec4(c->reg.dp1), deref_4f(vtx1, c->offset_hpos), c->reg.plane_equation);
|
||||
is_negative = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
/*
|
||||
* Both can be negative on GM965/G965 due to RHW workaround
|
||||
* if so, this object should be rejected.
|
||||
*/
|
||||
if (c->chipset.is_965) {
|
||||
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, c->reg.dp0, brw_imm_f(0.0));
|
||||
is_neg2 = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_clip_kill_thread(c);
|
||||
}
|
||||
brw_ENDIF(p, is_neg2);
|
||||
}
|
||||
|
||||
brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0));
|
||||
brw_math_invert(p, c->reg.t, c->reg.t);
|
||||
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1);
|
||||
|
||||
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 );
|
||||
brw_MOV(p, c->reg.t1, c->reg.t);
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
}
|
||||
is_negative = brw_ELSE(p, is_negative);
|
||||
{
|
||||
/* Coming back in. We know that both cannot be negative
|
||||
* because the line would have been culled in that case.
|
||||
*/
|
||||
|
||||
/* If both are positive, do nothing */
|
||||
/* Only on GM965/G965 */
|
||||
if (c->chipset.is_965) {
|
||||
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));
|
||||
is_neg2 = brw_IF(p, BRW_EXECUTE_1);
|
||||
}
|
||||
|
||||
{
|
||||
brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1));
|
||||
brw_math_invert(p, c->reg.t, c->reg.t);
|
||||
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0);
|
||||
|
||||
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 );
|
||||
brw_MOV(p, c->reg.t0, c->reg.t);
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
}
|
||||
|
||||
if (c->chipset.is_965) {
|
||||
brw_ENDIF(p, is_neg2);
|
||||
}
|
||||
}
|
||||
brw_ENDIF(p, is_negative);
|
||||
}
|
||||
brw_ENDIF(p, plane_active);
|
||||
|
||||
/* plane_ptr++;
|
||||
*/
|
||||
brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
|
||||
|
||||
/* while (planemask>>=1) != 0
|
||||
*/
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
|
||||
}
|
||||
brw_WHILE(p, plane_loop);
|
||||
|
||||
brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1);
|
||||
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0));
|
||||
not_culled = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, FALSE);
|
||||
brw_clip_interp_vertex(c, newvtx1, vtx1, vtx0, c->reg.t1, FALSE);
|
||||
|
||||
brw_clip_emit_vue(c, newvtx0, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_START);
|
||||
brw_clip_emit_vue(c, newvtx1, 0, 1, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_END);
|
||||
}
|
||||
brw_ENDIF(p, not_culled);
|
||||
brw_clip_kill_thread(c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void brw_emit_line_clip( struct brw_clip_compile *c )
|
||||
{
|
||||
brw_clip_line_alloc_regs(c);
|
||||
brw_clip_init_ff_sync(c);
|
||||
|
||||
if (c->key.do_flat_shading)
|
||||
brw_clip_copy_colors(c, 0, 1);
|
||||
|
||||
clip_and_emit_line(c);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "brw_defines.h"
|
||||
#include "brw_eu.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_clip.h"
|
||||
|
||||
|
||||
/* Point clipping, nothing to do?
|
||||
*/
|
||||
void brw_emit_point_clip( struct brw_clip_compile *c )
|
||||
{
|
||||
/* Send an empty message to kill the thread:
|
||||
*/
|
||||
brw_clip_tri_alloc_regs(c, 0);
|
||||
brw_clip_init_ff_sync(c);
|
||||
|
||||
brw_clip_kill_thread(c);
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_clip.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_debug.h"
|
||||
|
||||
struct brw_clip_unit_key {
|
||||
unsigned int total_grf;
|
||||
unsigned int urb_entry_read_length;
|
||||
unsigned int curb_entry_read_length;
|
||||
unsigned int clip_mode;
|
||||
|
||||
unsigned int curbe_offset;
|
||||
|
||||
unsigned int nr_urb_entries, urb_size;
|
||||
|
||||
GLboolean depth_clamp;
|
||||
};
|
||||
|
||||
static void
|
||||
clip_unit_populate_key(struct brw_context *brw, struct brw_clip_unit_key *key)
|
||||
{
|
||||
memset(key, 0, sizeof(*key));
|
||||
|
||||
/* CACHE_NEW_CLIP_PROG */
|
||||
key->total_grf = brw->clip.prog_data->total_grf;
|
||||
key->urb_entry_read_length = brw->clip.prog_data->urb_read_length;
|
||||
key->curb_entry_read_length = brw->clip.prog_data->curb_read_length;
|
||||
key->clip_mode = brw->clip.prog_data->clip_mode;
|
||||
|
||||
/* BRW_NEW_CURBE_OFFSETS */
|
||||
key->curbe_offset = brw->curbe.clip_start;
|
||||
|
||||
/* BRW_NEW_URB_FENCE */
|
||||
key->nr_urb_entries = brw->urb.nr_clip_entries;
|
||||
key->urb_size = brw->urb.vsize;
|
||||
|
||||
/* */
|
||||
key->depth_clamp = 0; /* XXX: add this to gallium: ctx->Transform.DepthClamp; */
|
||||
}
|
||||
|
||||
static enum pipe_error
|
||||
clip_unit_create_from_key(struct brw_context *brw,
|
||||
struct brw_clip_unit_key *key,
|
||||
struct brw_winsys_reloc *reloc,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
struct brw_clip_unit_state clip;
|
||||
enum pipe_error ret;
|
||||
|
||||
memset(&clip, 0, sizeof(clip));
|
||||
|
||||
clip.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
|
||||
/* reloc */
|
||||
clip.thread0.kernel_start_pointer = 0;
|
||||
|
||||
clip.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
|
||||
clip.thread1.single_program_flow = 1;
|
||||
|
||||
clip.thread3.urb_entry_read_length = key->urb_entry_read_length;
|
||||
clip.thread3.const_urb_entry_read_length = key->curb_entry_read_length;
|
||||
clip.thread3.const_urb_entry_read_offset = key->curbe_offset * 2;
|
||||
clip.thread3.dispatch_grf_start_reg = 1;
|
||||
clip.thread3.urb_entry_read_offset = 0;
|
||||
|
||||
clip.thread4.nr_urb_entries = key->nr_urb_entries;
|
||||
clip.thread4.urb_entry_allocation_size = key->urb_size - 1;
|
||||
/* If we have enough clip URB entries to run two threads, do so.
|
||||
*/
|
||||
if (key->nr_urb_entries >= 10) {
|
||||
/* Half of the URB entries go to each thread, and it has to be an
|
||||
* even number.
|
||||
*/
|
||||
assert(key->nr_urb_entries % 2 == 0);
|
||||
|
||||
/* Although up to 16 concurrent Clip threads are allowed on IGDNG,
|
||||
* only 2 threads can output VUEs at a time.
|
||||
*/
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
clip.thread4.max_threads = 16 - 1;
|
||||
else
|
||||
clip.thread4.max_threads = 2 - 1;
|
||||
} else {
|
||||
assert(key->nr_urb_entries >= 5);
|
||||
clip.thread4.max_threads = 1 - 1;
|
||||
}
|
||||
|
||||
if (BRW_DEBUG & DEBUG_SINGLE_THREAD)
|
||||
clip.thread4.max_threads = 0;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_STATS)
|
||||
clip.thread4.stats_enable = 1;
|
||||
|
||||
clip.clip5.userclip_enable_flags = 0x7f;
|
||||
clip.clip5.userclip_must_clip = 1;
|
||||
clip.clip5.guard_band_enable = 0;
|
||||
if (!key->depth_clamp)
|
||||
clip.clip5.viewport_z_clip_enable = 1;
|
||||
clip.clip5.viewport_xy_clip_enable = 1;
|
||||
clip.clip5.vertex_position_space = BRW_CLIP_NDCSPACE;
|
||||
clip.clip5.api_mode = BRW_CLIP_API_OGL;
|
||||
clip.clip5.clip_mode = key->clip_mode;
|
||||
|
||||
if (BRW_IS_G4X(brw))
|
||||
clip.clip5.negative_w_clip_test = 1;
|
||||
|
||||
clip.clip6.clipper_viewport_state_ptr = 0;
|
||||
clip.viewport_xmin = -1;
|
||||
clip.viewport_xmax = 1;
|
||||
clip.viewport_ymin = -1;
|
||||
clip.viewport_ymax = 1;
|
||||
|
||||
ret = brw_upload_cache(&brw->cache, BRW_CLIP_UNIT,
|
||||
key, sizeof(*key),
|
||||
reloc, 1,
|
||||
&clip, sizeof(clip),
|
||||
NULL, NULL,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
static int upload_clip_unit( struct brw_context *brw )
|
||||
{
|
||||
struct brw_clip_unit_key key;
|
||||
struct brw_winsys_reloc reloc[1];
|
||||
unsigned grf_reg_count;
|
||||
enum pipe_error ret;
|
||||
|
||||
clip_unit_populate_key(brw, &key);
|
||||
|
||||
grf_reg_count = align(key.total_grf, 16) / 16 - 1;
|
||||
|
||||
/* clip program relocation
|
||||
*
|
||||
* XXX: these reloc structs are long lived and only need to be
|
||||
* updated when the bound BO changes. Hopefully the stuff mixed in
|
||||
* in the delta's is non-orthogonal.
|
||||
*/
|
||||
assert(brw->clip.prog_bo);
|
||||
make_reloc(&reloc[0],
|
||||
BRW_USAGE_STATE,
|
||||
grf_reg_count << 1,
|
||||
offsetof(struct brw_clip_unit_state, thread0),
|
||||
brw->clip.prog_bo);
|
||||
|
||||
|
||||
if (brw_search_cache(&brw->cache, BRW_CLIP_UNIT,
|
||||
&key, sizeof(key),
|
||||
reloc, 1,
|
||||
NULL,
|
||||
&brw->clip.state_bo))
|
||||
return PIPE_OK;
|
||||
|
||||
/* Create new:
|
||||
*/
|
||||
ret = clip_unit_create_from_key(brw, &key,
|
||||
reloc,
|
||||
&brw->clip.state_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_clip_unit = {
|
||||
.dirty = {
|
||||
.mesa = 0,
|
||||
.brw = (BRW_NEW_CURBE_OFFSETS |
|
||||
BRW_NEW_URB_FENCE),
|
||||
.cache = CACHE_NEW_CLIP_PROG
|
||||
},
|
||||
.prepare = upload_clip_unit,
|
||||
};
|
||||
@@ -0,0 +1,595 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "brw_defines.h"
|
||||
#include "brw_eu.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_clip.h"
|
||||
|
||||
static void release_tmps( struct brw_clip_compile *c )
|
||||
{
|
||||
c->last_tmp = c->first_tmp;
|
||||
}
|
||||
|
||||
|
||||
void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
|
||||
GLuint nr_verts )
|
||||
{
|
||||
GLuint i = 0,j;
|
||||
|
||||
/* Register usage is static, precompute here:
|
||||
*/
|
||||
c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
|
||||
|
||||
if (c->key.nr_userclip) {
|
||||
c->reg.fixed_planes = brw_vec4_grf(i, 0);
|
||||
i += (6 + c->key.nr_userclip + 1) / 2;
|
||||
|
||||
c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
|
||||
}
|
||||
else
|
||||
c->prog_data.curb_read_length = 0;
|
||||
|
||||
|
||||
/* Payload vertices plus space for more generated vertices:
|
||||
*/
|
||||
for (j = 0; j < nr_verts; j++) {
|
||||
c->reg.vertex[j] = brw_vec4_grf(i, 0);
|
||||
i += c->nr_regs;
|
||||
}
|
||||
|
||||
if (c->key.nr_attrs & 1) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
GLuint delta = c->key.nr_attrs*16 + 32;
|
||||
|
||||
if (c->chipset.is_igdng)
|
||||
delta = c->key.nr_attrs * 16 + 32 * 3;
|
||||
|
||||
brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0));
|
||||
}
|
||||
}
|
||||
|
||||
c->reg.t = brw_vec1_grf(i, 0);
|
||||
c->reg.loopcount = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_D);
|
||||
c->reg.nr_verts = retype(brw_vec1_grf(i, 2), BRW_REGISTER_TYPE_UD);
|
||||
c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
|
||||
c->reg.plane_equation = brw_vec4_grf(i, 4);
|
||||
i++;
|
||||
|
||||
c->reg.dpPrev = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
|
||||
c->reg.dp = brw_vec1_grf(i, 4);
|
||||
i++;
|
||||
|
||||
c->reg.inlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
|
||||
i++;
|
||||
|
||||
c->reg.outlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
|
||||
i++;
|
||||
|
||||
c->reg.freelist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
|
||||
i++;
|
||||
|
||||
if (!c->key.nr_userclip) {
|
||||
c->reg.fixed_planes = brw_vec8_grf(i, 0);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (c->key.do_unfilled) {
|
||||
c->reg.dir = brw_vec4_grf(i, 0);
|
||||
c->reg.offset = brw_vec4_grf(i, 4);
|
||||
i++;
|
||||
c->reg.tmp0 = brw_vec4_grf(i, 0);
|
||||
c->reg.tmp1 = brw_vec4_grf(i, 4);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (c->need_ff_sync) {
|
||||
c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
|
||||
i++;
|
||||
}
|
||||
|
||||
c->first_tmp = i;
|
||||
c->last_tmp = i;
|
||||
|
||||
c->prog_data.urb_read_length = c->nr_regs; /* ? */
|
||||
c->prog_data.total_grf = i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void brw_clip_tri_init_vertices( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
|
||||
struct brw_instruction *is_rev;
|
||||
|
||||
/* Initial list of indices for incoming vertexes:
|
||||
*/
|
||||
brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
|
||||
brw_CMP(p,
|
||||
vec1(brw_null_reg()),
|
||||
BRW_CONDITIONAL_EQ,
|
||||
tmp0,
|
||||
brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));
|
||||
|
||||
/* XXX: Is there an easier way to do this? Need to reverse every
|
||||
* second tristrip element: Can ignore sometimes?
|
||||
*/
|
||||
is_rev = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[1]) );
|
||||
brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[0]) );
|
||||
if (c->need_direction)
|
||||
brw_MOV(p, c->reg.dir, brw_imm_f(-1));
|
||||
}
|
||||
is_rev = brw_ELSE(p, is_rev);
|
||||
{
|
||||
brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[0]) );
|
||||
brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[1]) );
|
||||
if (c->need_direction)
|
||||
brw_MOV(p, c->reg.dir, brw_imm_f(1));
|
||||
}
|
||||
brw_ENDIF(p, is_rev);
|
||||
|
||||
brw_MOV(p, get_element(c->reg.inlist, 2), brw_address(c->reg.vertex[2]) );
|
||||
brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0));
|
||||
brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void brw_clip_tri_flat_shade( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *is_poly;
|
||||
struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
|
||||
|
||||
brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
|
||||
brw_CMP(p,
|
||||
vec1(brw_null_reg()),
|
||||
BRW_CONDITIONAL_EQ,
|
||||
tmp0,
|
||||
brw_imm_ud(_3DPRIM_POLYGON));
|
||||
|
||||
is_poly = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_clip_copy_colors(c, 1, 0);
|
||||
brw_clip_copy_colors(c, 2, 0);
|
||||
}
|
||||
is_poly = brw_ELSE(p, is_poly);
|
||||
{
|
||||
brw_clip_copy_colors(c, 0, 2);
|
||||
brw_clip_copy_colors(c, 1, 2);
|
||||
}
|
||||
brw_ENDIF(p, is_poly);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Use mesa's clipping algorithms, translated to GEN4 assembly.
|
||||
*/
|
||||
void brw_clip_tri( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_indirect vtx = brw_indirect(0, 0);
|
||||
struct brw_indirect vtxPrev = brw_indirect(1, 0);
|
||||
struct brw_indirect vtxOut = brw_indirect(2, 0);
|
||||
struct brw_indirect plane_ptr = brw_indirect(3, 0);
|
||||
struct brw_indirect inlist_ptr = brw_indirect(4, 0);
|
||||
struct brw_indirect outlist_ptr = brw_indirect(5, 0);
|
||||
struct brw_indirect freelist_ptr = brw_indirect(6, 0);
|
||||
struct brw_instruction *plane_loop;
|
||||
struct brw_instruction *plane_active;
|
||||
struct brw_instruction *vertex_loop;
|
||||
struct brw_instruction *next_test;
|
||||
struct brw_instruction *prev_test;
|
||||
|
||||
brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) );
|
||||
brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
|
||||
brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
|
||||
brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
|
||||
|
||||
brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) );
|
||||
|
||||
plane_loop = brw_DO(p, BRW_EXECUTE_1);
|
||||
{
|
||||
/* if (planemask & 1)
|
||||
*/
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1));
|
||||
|
||||
plane_active = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
/* vtxOut = freelist_ptr++
|
||||
*/
|
||||
brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) );
|
||||
brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE));
|
||||
|
||||
if (c->key.nr_userclip)
|
||||
brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
|
||||
else
|
||||
brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
|
||||
|
||||
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
|
||||
brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0));
|
||||
|
||||
vertex_loop = brw_DO(p, BRW_EXECUTE_1);
|
||||
{
|
||||
/* vtx = *input_ptr;
|
||||
*/
|
||||
brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0));
|
||||
|
||||
/* IS_NEGATIVE(prev) */
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
|
||||
brw_DP4(p, vec4(c->reg.dpPrev), deref_4f(vtxPrev, c->offset_hpos), c->reg.plane_equation);
|
||||
prev_test = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
/* IS_POSITIVE(next)
|
||||
*/
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_GE);
|
||||
brw_DP4(p, vec4(c->reg.dp), deref_4f(vtx, c->offset_hpos), c->reg.plane_equation);
|
||||
next_test = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
|
||||
/* Coming back in.
|
||||
*/
|
||||
brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp));
|
||||
brw_math_invert(p, c->reg.t, c->reg.t);
|
||||
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev);
|
||||
|
||||
/* If (vtxOut == 0) vtxOut = vtxPrev
|
||||
*/
|
||||
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
|
||||
brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev) );
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
|
||||
brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, GL_FALSE);
|
||||
|
||||
/* *outlist_ptr++ = vtxOut;
|
||||
* nr_verts++;
|
||||
* vtxOut = 0;
|
||||
*/
|
||||
brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
|
||||
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
|
||||
brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
|
||||
brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
|
||||
}
|
||||
brw_ENDIF(p, next_test);
|
||||
|
||||
}
|
||||
prev_test = brw_ELSE(p, prev_test);
|
||||
{
|
||||
/* *outlist_ptr++ = vtxPrev;
|
||||
* nr_verts++;
|
||||
*/
|
||||
brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev));
|
||||
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
|
||||
brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
|
||||
|
||||
/* IS_NEGATIVE(next)
|
||||
*/
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
|
||||
brw_DP4(p, vec4(c->reg.dp), deref_4f(vtx, c->offset_hpos), c->reg.plane_equation);
|
||||
next_test = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
/* Going out of bounds. Avoid division by zero as we
|
||||
* know dp != dpPrev from DIFFERENT_SIGNS, above.
|
||||
*/
|
||||
brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev));
|
||||
brw_math_invert(p, c->reg.t, c->reg.t);
|
||||
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp);
|
||||
|
||||
/* If (vtxOut == 0) vtxOut = vtx
|
||||
*/
|
||||
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
|
||||
brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx) );
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
|
||||
brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, GL_TRUE);
|
||||
|
||||
/* *outlist_ptr++ = vtxOut;
|
||||
* nr_verts++;
|
||||
* vtxOut = 0;
|
||||
*/
|
||||
brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
|
||||
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
|
||||
brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
|
||||
brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
|
||||
}
|
||||
brw_ENDIF(p, next_test);
|
||||
}
|
||||
brw_ENDIF(p, prev_test);
|
||||
|
||||
/* vtxPrev = vtx;
|
||||
* inlist_ptr++;
|
||||
*/
|
||||
brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx));
|
||||
brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short)));
|
||||
|
||||
/* while (--loopcount != 0)
|
||||
*/
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
|
||||
}
|
||||
brw_WHILE(p, vertex_loop);
|
||||
|
||||
/* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
|
||||
* inlist = outlist
|
||||
* inlist_ptr = &inlist[0]
|
||||
* outlist_ptr = &outlist[0]
|
||||
*/
|
||||
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2));
|
||||
brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0));
|
||||
brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0));
|
||||
brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
|
||||
brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
|
||||
}
|
||||
brw_ENDIF(p, plane_active);
|
||||
|
||||
/* plane_ptr++;
|
||||
*/
|
||||
brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
|
||||
|
||||
/* nr_verts >= 3
|
||||
*/
|
||||
brw_CMP(p,
|
||||
vec1(brw_null_reg()),
|
||||
BRW_CONDITIONAL_GE,
|
||||
c->reg.nr_verts,
|
||||
brw_imm_ud(3));
|
||||
|
||||
/* && (planemask>>=1) != 0
|
||||
*/
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
|
||||
}
|
||||
brw_WHILE(p, plane_loop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void brw_clip_tri_emit_polygon(struct brw_clip_compile *c)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *loop, *if_insn;
|
||||
|
||||
/* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
|
||||
*/
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
|
||||
brw_ADD(p,
|
||||
c->reg.loopcount,
|
||||
c->reg.nr_verts,
|
||||
brw_imm_d(-2));
|
||||
|
||||
if_insn = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
struct brw_indirect v0 = brw_indirect(0, 0);
|
||||
struct brw_indirect vptr = brw_indirect(1, 0);
|
||||
|
||||
brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist));
|
||||
brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
|
||||
|
||||
brw_clip_emit_vue(c, v0, 1, 0, ((_3DPRIM_TRIFAN << 2) | R02_PRIM_START));
|
||||
|
||||
brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
|
||||
brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
|
||||
|
||||
loop = brw_DO(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_TRIFAN << 2));
|
||||
|
||||
brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
|
||||
brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
|
||||
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
|
||||
}
|
||||
brw_WHILE(p, loop);
|
||||
|
||||
brw_clip_emit_vue(c, v0, 0, 1, ((_3DPRIM_TRIFAN << 2) | R02_PRIM_END));
|
||||
}
|
||||
brw_ENDIF(p, if_insn);
|
||||
}
|
||||
|
||||
static void do_clip_tri( struct brw_clip_compile *c )
|
||||
{
|
||||
brw_clip_init_planes(c);
|
||||
|
||||
brw_clip_tri(c);
|
||||
}
|
||||
|
||||
|
||||
static void maybe_do_clip_tri( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *do_clip;
|
||||
|
||||
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
|
||||
do_clip = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
do_clip_tri(c);
|
||||
}
|
||||
brw_ENDIF(p, do_clip);
|
||||
}
|
||||
|
||||
static void brw_clip_test( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
|
||||
struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
|
||||
struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
|
||||
struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
|
||||
|
||||
struct brw_reg v0 = get_tmp(c);
|
||||
struct brw_reg v1 = get_tmp(c);
|
||||
struct brw_reg v2 = get_tmp(c);
|
||||
|
||||
struct brw_indirect vt0 = brw_indirect(0, 0);
|
||||
struct brw_indirect vt1 = brw_indirect(1, 0);
|
||||
struct brw_indirect vt2 = brw_indirect(2, 0);
|
||||
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *is_outside;
|
||||
struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
|
||||
|
||||
brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
|
||||
brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
|
||||
brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2]));
|
||||
brw_MOV(p, v0, deref_4f(vt0, c->offset_hpos));
|
||||
brw_MOV(p, v1, deref_4f(vt1, c->offset_hpos));
|
||||
brw_MOV(p, v2, deref_4f(vt2, c->offset_hpos));
|
||||
brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f));
|
||||
|
||||
/* test nearz, xmin, ymin plane */
|
||||
/* clip.xyz < -clip.w */
|
||||
brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3)));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
|
||||
/* All vertices are outside of a plane, rejected */
|
||||
brw_AND(p, t, t1, t2);
|
||||
brw_AND(p, t, t, t3);
|
||||
brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
|
||||
brw_OR(p, tmp0, tmp0, get_element(t, 2));
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
|
||||
is_outside = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_clip_kill_thread(c);
|
||||
}
|
||||
brw_ENDIF(p, is_outside);
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
|
||||
/* some vertices are inside a plane, some are outside,need to clip */
|
||||
brw_XOR(p, t, t1, t2);
|
||||
brw_XOR(p, t1, t2, t3);
|
||||
brw_OR(p, t, t, t1);
|
||||
brw_AND(p, t, t, brw_imm_ud(0x1));
|
||||
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
|
||||
get_element(t, 0), brw_imm_ud(0));
|
||||
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
|
||||
get_element(t, 1), brw_imm_ud(0));
|
||||
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
|
||||
get_element(t, 2), brw_imm_ud(0));
|
||||
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
|
||||
/* test farz, xmax, ymax plane */
|
||||
/* clip.xyz > clip.w */
|
||||
brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
|
||||
/* All vertices are outside of a plane, rejected */
|
||||
brw_AND(p, t, t1, t2);
|
||||
brw_AND(p, t, t, t3);
|
||||
brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
|
||||
brw_OR(p, tmp0, tmp0, get_element(t, 2));
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
|
||||
is_outside = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_clip_kill_thread(c);
|
||||
}
|
||||
brw_ENDIF(p, is_outside);
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
|
||||
/* some vertices are inside a plane, some are outside,need to clip */
|
||||
brw_XOR(p, t, t1, t2);
|
||||
brw_XOR(p, t1, t2, t3);
|
||||
brw_OR(p, t, t, t1);
|
||||
brw_AND(p, t, t, brw_imm_ud(0x1));
|
||||
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
|
||||
get_element(t, 0), brw_imm_ud(0));
|
||||
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
|
||||
get_element(t, 1), brw_imm_ud(0));
|
||||
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
|
||||
get_element(t, 2), brw_imm_ud(0));
|
||||
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
|
||||
release_tmps(c);
|
||||
}
|
||||
|
||||
|
||||
void brw_emit_tri_clip( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_instruction *neg_rhw;
|
||||
struct brw_compile *p = &c->func;
|
||||
brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
|
||||
brw_clip_tri_init_vertices(c);
|
||||
brw_clip_init_clipmask(c);
|
||||
brw_clip_init_ff_sync(c);
|
||||
|
||||
/* if -ve rhw workaround bit is set,
|
||||
do cliptest */
|
||||
if (c->chipset.is_965) {
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
|
||||
brw_imm_ud(1<<20));
|
||||
neg_rhw = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_clip_test(c);
|
||||
}
|
||||
brw_ENDIF(p, neg_rhw);
|
||||
}
|
||||
/* Can't push into do_clip_tri because with polygon (or quad)
|
||||
* flatshading, need to apply the flatshade here because we don't
|
||||
* respect the PV when converting to trifan for emit:
|
||||
*/
|
||||
if (c->key.do_flat_shading)
|
||||
brw_clip_tri_flat_shade(c);
|
||||
|
||||
if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) ||
|
||||
(c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP))
|
||||
do_clip_tri(c);
|
||||
else
|
||||
maybe_do_clip_tri(c);
|
||||
|
||||
brw_clip_tri_emit_polygon(c);
|
||||
|
||||
/* Send an empty message to kill the thread:
|
||||
*/
|
||||
brw_clip_kill_thread(c);
|
||||
}
|
||||
@@ -0,0 +1,497 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "brw_defines.h"
|
||||
#include "brw_eu.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_clip.h"
|
||||
|
||||
|
||||
|
||||
/* This is performed against the original triangles, so no indirection
|
||||
* required:
|
||||
BZZZT!
|
||||
*/
|
||||
static void compute_tri_direction( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_reg e = c->reg.tmp0;
|
||||
struct brw_reg f = c->reg.tmp1;
|
||||
struct brw_reg v0 = byte_offset(c->reg.vertex[0], c->offset_hpos);
|
||||
struct brw_reg v1 = byte_offset(c->reg.vertex[1], c->offset_hpos);
|
||||
struct brw_reg v2 = byte_offset(c->reg.vertex[2], c->offset_hpos);
|
||||
|
||||
|
||||
struct brw_reg v0n = get_tmp(c);
|
||||
struct brw_reg v1n = get_tmp(c);
|
||||
struct brw_reg v2n = get_tmp(c);
|
||||
|
||||
/* Convert to NDC.
|
||||
* NOTE: We can't modify the original vertex coordinates,
|
||||
* as it may impact further operations.
|
||||
* So, we have to keep normalized coordinates in temp registers.
|
||||
*
|
||||
* TBD-KC
|
||||
* Try to optimize unnecessary MOV's.
|
||||
*/
|
||||
brw_MOV(p, v0n, v0);
|
||||
brw_MOV(p, v1n, v1);
|
||||
brw_MOV(p, v2n, v2);
|
||||
|
||||
brw_clip_project_position(c, v0n);
|
||||
brw_clip_project_position(c, v1n);
|
||||
brw_clip_project_position(c, v2n);
|
||||
|
||||
/* Calculate the vectors of two edges of the triangle:
|
||||
*/
|
||||
brw_ADD(p, e, v0n, negate(v2n));
|
||||
brw_ADD(p, f, v1n, negate(v2n));
|
||||
|
||||
/* Take their crossproduct:
|
||||
*/
|
||||
brw_set_access_mode(p, BRW_ALIGN_16);
|
||||
brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, 1,2,0,3), brw_swizzle(f,2,0,1,3));
|
||||
brw_MAC(p, vec4(e), negate(brw_swizzle(e, 2,0,1,3)), brw_swizzle(f,1,2,0,3));
|
||||
brw_set_access_mode(p, BRW_ALIGN_1);
|
||||
|
||||
brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e));
|
||||
}
|
||||
|
||||
|
||||
static void cull_direction( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *ccw;
|
||||
GLuint conditional;
|
||||
|
||||
assert (!(c->key.fill_ccw == CLIP_CULL &&
|
||||
c->key.fill_cw == CLIP_CULL));
|
||||
|
||||
if (c->key.fill_ccw == CLIP_CULL)
|
||||
conditional = BRW_CONDITIONAL_GE;
|
||||
else
|
||||
conditional = BRW_CONDITIONAL_L;
|
||||
|
||||
brw_CMP(p,
|
||||
vec1(brw_null_reg()),
|
||||
conditional,
|
||||
get_element(c->reg.dir, 2),
|
||||
brw_imm_f(0));
|
||||
|
||||
ccw = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_clip_kill_thread(c);
|
||||
}
|
||||
brw_ENDIF(p, ccw);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void copy_bfc( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *ccw;
|
||||
GLuint conditional;
|
||||
|
||||
/* Do we have any colors to copy?
|
||||
*/
|
||||
if ((c->offset_color0 == 0 || c->offset_bfc0 == 0) &&
|
||||
(c->offset_color1 == 0 || c->offset_bfc1 == 0))
|
||||
return;
|
||||
|
||||
/* In some wierd degnerate cases we can end up testing the
|
||||
* direction twice, once for culling and once for bfc copying. Oh
|
||||
* well, that's what you get for setting wierd GL state.
|
||||
*/
|
||||
if (c->key.copy_bfc_ccw)
|
||||
conditional = BRW_CONDITIONAL_GE;
|
||||
else
|
||||
conditional = BRW_CONDITIONAL_L;
|
||||
|
||||
brw_CMP(p,
|
||||
vec1(brw_null_reg()),
|
||||
conditional,
|
||||
get_element(c->reg.dir, 2),
|
||||
brw_imm_f(0));
|
||||
|
||||
ccw = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (c->offset_color0 && c->offset_bfc0)
|
||||
brw_MOV(p,
|
||||
byte_offset(c->reg.vertex[i], c->offset_color0),
|
||||
byte_offset(c->reg.vertex[i], c->offset_bfc0));
|
||||
|
||||
if (c->offset_color1 && c->offset_bfc1)
|
||||
brw_MOV(p,
|
||||
byte_offset(c->reg.vertex[i], c->offset_color0),
|
||||
byte_offset(c->reg.vertex[i], c->offset_bfc0));
|
||||
}
|
||||
}
|
||||
brw_ENDIF(p, ccw);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
GLfloat iz = 1.0 / dir.z;
|
||||
GLfloat ac = dir.x * iz;
|
||||
GLfloat bc = dir.y * iz;
|
||||
offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
|
||||
offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor;
|
||||
offset *= MRD;
|
||||
*/
|
||||
static void compute_offset( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_reg off = c->reg.offset;
|
||||
struct brw_reg dir = c->reg.dir;
|
||||
|
||||
brw_math_invert(p, get_element(off, 2), get_element(dir, 2));
|
||||
brw_MUL(p, vec2(off), dir, get_element(off, 2));
|
||||
|
||||
brw_CMP(p,
|
||||
vec1(brw_null_reg()),
|
||||
BRW_CONDITIONAL_GE,
|
||||
brw_abs(get_element(off, 0)),
|
||||
brw_abs(get_element(off, 1)));
|
||||
|
||||
brw_SEL(p, vec1(off), brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1)));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
|
||||
brw_MUL(p, vec1(off), off, brw_imm_f(c->key.offset_factor));
|
||||
brw_ADD(p, vec1(off), off, brw_imm_f(c->key.offset_units));
|
||||
}
|
||||
|
||||
|
||||
static void merge_edgeflags( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *is_poly;
|
||||
struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0);
|
||||
|
||||
brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
|
||||
brw_CMP(p,
|
||||
vec1(brw_null_reg()),
|
||||
BRW_CONDITIONAL_EQ,
|
||||
tmp0,
|
||||
brw_imm_ud(_3DPRIM_POLYGON));
|
||||
|
||||
/* Get away with using reg.vertex because we know that this is not
|
||||
* a _3DPRIM_TRISTRIP_REVERSE:
|
||||
*/
|
||||
is_poly = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_EQ);
|
||||
brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8));
|
||||
brw_MOV(p, byte_offset(c->reg.vertex[0], c->offset_edgeflag), brw_imm_f(0));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_EQ);
|
||||
brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9));
|
||||
brw_MOV(p, byte_offset(c->reg.vertex[2], c->offset_edgeflag), brw_imm_f(0));
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
}
|
||||
brw_ENDIF(p, is_poly);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void apply_one_offset( struct brw_clip_compile *c,
|
||||
struct brw_indirect vert )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_reg z = deref_1f(vert, c->header_position_offset +
|
||||
2 * type_sz(BRW_REGISTER_TYPE_F));
|
||||
|
||||
brw_ADD(p, z, z, vec1(c->reg.offset));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Output clipped polygon as an unfilled primitive:
|
||||
*/
|
||||
static void emit_lines(struct brw_clip_compile *c,
|
||||
GLboolean do_offset)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *loop;
|
||||
struct brw_instruction *draw_edge;
|
||||
struct brw_indirect v0 = brw_indirect(0, 0);
|
||||
struct brw_indirect v1 = brw_indirect(1, 0);
|
||||
struct brw_indirect v0ptr = brw_indirect(2, 0);
|
||||
struct brw_indirect v1ptr = brw_indirect(3, 0);
|
||||
|
||||
/* Need a seperate loop for offset:
|
||||
*/
|
||||
if (do_offset) {
|
||||
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
|
||||
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
|
||||
|
||||
loop = brw_DO(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
|
||||
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
|
||||
|
||||
apply_one_offset(c, v0);
|
||||
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
|
||||
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
|
||||
}
|
||||
brw_WHILE(p, loop);
|
||||
}
|
||||
|
||||
/* v1ptr = &inlist[nr_verts]
|
||||
* *v1ptr = v0
|
||||
*/
|
||||
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
|
||||
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
|
||||
brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
|
||||
brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
|
||||
brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0));
|
||||
|
||||
loop = brw_DO(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
|
||||
brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2));
|
||||
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
|
||||
|
||||
/* draw edge if edgeflag != 0 */
|
||||
brw_CMP(p,
|
||||
vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
|
||||
deref_1f(v0, c->offset_edgeflag),
|
||||
brw_imm_f(0));
|
||||
draw_edge = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_START);
|
||||
brw_clip_emit_vue(c, v1, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_END);
|
||||
}
|
||||
brw_ENDIF(p, draw_edge);
|
||||
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
|
||||
}
|
||||
brw_WHILE(p, loop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void emit_points(struct brw_clip_compile *c,
|
||||
GLboolean do_offset )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *loop;
|
||||
struct brw_instruction *draw_point;
|
||||
|
||||
struct brw_indirect v0 = brw_indirect(0, 0);
|
||||
struct brw_indirect v0ptr = brw_indirect(2, 0);
|
||||
|
||||
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
|
||||
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
|
||||
|
||||
loop = brw_DO(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
|
||||
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
|
||||
|
||||
/* draw if edgeflag != 0
|
||||
*/
|
||||
brw_CMP(p,
|
||||
vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
|
||||
deref_1f(v0, c->offset_edgeflag),
|
||||
brw_imm_f(0));
|
||||
draw_point = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
if (do_offset)
|
||||
apply_one_offset(c, v0);
|
||||
|
||||
brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_POINTLIST << 2) | R02_PRIM_START | R02_PRIM_END);
|
||||
}
|
||||
brw_ENDIF(p, draw_point);
|
||||
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
|
||||
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
|
||||
}
|
||||
brw_WHILE(p, loop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void emit_primitives( struct brw_clip_compile *c,
|
||||
GLuint mode,
|
||||
GLboolean do_offset )
|
||||
{
|
||||
switch (mode) {
|
||||
case CLIP_FILL:
|
||||
brw_clip_tri_emit_polygon(c);
|
||||
break;
|
||||
|
||||
case CLIP_LINE:
|
||||
emit_lines(c, do_offset);
|
||||
break;
|
||||
|
||||
case CLIP_POINT:
|
||||
emit_points(c, do_offset);
|
||||
break;
|
||||
|
||||
case CLIP_CULL:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void emit_unfilled_primitives( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *ccw;
|
||||
|
||||
/* Direction culling has already been done.
|
||||
*/
|
||||
if (c->key.fill_ccw != c->key.fill_cw &&
|
||||
c->key.fill_ccw != CLIP_CULL &&
|
||||
c->key.fill_cw != CLIP_CULL)
|
||||
{
|
||||
brw_CMP(p,
|
||||
vec1(brw_null_reg()),
|
||||
BRW_CONDITIONAL_GE,
|
||||
get_element(c->reg.dir, 2),
|
||||
brw_imm_f(0));
|
||||
|
||||
ccw = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
|
||||
}
|
||||
ccw = brw_ELSE(p, ccw);
|
||||
{
|
||||
emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
|
||||
}
|
||||
brw_ENDIF(p, ccw);
|
||||
}
|
||||
else if (c->key.fill_cw != CLIP_CULL) {
|
||||
emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
|
||||
}
|
||||
else if (c->key.fill_ccw != CLIP_CULL) {
|
||||
emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void check_nr_verts( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *if_insn;
|
||||
|
||||
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3));
|
||||
if_insn = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_clip_kill_thread(c);
|
||||
}
|
||||
brw_ENDIF(p, if_insn);
|
||||
}
|
||||
|
||||
|
||||
void brw_emit_unfilled_clip( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *do_clip;
|
||||
|
||||
|
||||
c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) ||
|
||||
(c->key.fill_ccw != c->key.fill_cw) ||
|
||||
c->key.fill_ccw == CLIP_CULL ||
|
||||
c->key.fill_cw == CLIP_CULL ||
|
||||
c->key.copy_bfc_cw ||
|
||||
c->key.copy_bfc_ccw);
|
||||
|
||||
brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
|
||||
brw_clip_tri_init_vertices(c);
|
||||
brw_clip_init_ff_sync(c);
|
||||
|
||||
assert(c->offset_edgeflag);
|
||||
|
||||
if (c->key.fill_ccw == CLIP_CULL &&
|
||||
c->key.fill_cw == CLIP_CULL) {
|
||||
brw_clip_kill_thread(c);
|
||||
return;
|
||||
}
|
||||
|
||||
merge_edgeflags(c);
|
||||
|
||||
/* Need to use the inlist indirection here:
|
||||
*/
|
||||
if (c->need_direction)
|
||||
compute_tri_direction(c);
|
||||
|
||||
if (c->key.fill_ccw == CLIP_CULL ||
|
||||
c->key.fill_cw == CLIP_CULL)
|
||||
cull_direction(c);
|
||||
|
||||
if (c->key.offset_ccw ||
|
||||
c->key.offset_cw)
|
||||
compute_offset(c);
|
||||
|
||||
if (c->key.copy_bfc_ccw ||
|
||||
c->key.copy_bfc_cw)
|
||||
copy_bfc(c);
|
||||
|
||||
/* Need to do this whether we clip or not:
|
||||
*/
|
||||
if (c->key.do_flat_shading)
|
||||
brw_clip_tri_flat_shade(c);
|
||||
|
||||
brw_clip_init_clipmask(c);
|
||||
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
|
||||
do_clip = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_clip_init_planes(c);
|
||||
brw_clip_tri(c);
|
||||
check_nr_verts(c);
|
||||
}
|
||||
brw_ENDIF(p, do_clip);
|
||||
|
||||
emit_unfilled_primitives(c);
|
||||
brw_clip_kill_thread(c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "brw_defines.h"
|
||||
#include "brw_eu.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_clip.h"
|
||||
|
||||
|
||||
|
||||
|
||||
struct brw_reg get_tmp( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_reg tmp = brw_vec4_grf(c->last_tmp, 0);
|
||||
|
||||
if (++c->last_tmp > c->prog_data.total_grf)
|
||||
c->prog_data.total_grf = c->last_tmp;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static void release_tmp( struct brw_clip_compile *c, struct brw_reg tmp )
|
||||
{
|
||||
if (tmp.nr == c->last_tmp-1)
|
||||
c->last_tmp--;
|
||||
}
|
||||
|
||||
|
||||
static struct brw_reg make_plane_ud(GLuint x, GLuint y, GLuint z, GLuint w)
|
||||
{
|
||||
return brw_imm_ud((w<<24) | (z<<16) | (y<<8) | x);
|
||||
}
|
||||
|
||||
|
||||
void brw_clip_init_planes( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
|
||||
if (!c->key.nr_userclip) {
|
||||
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 0), make_plane_ud( 0, 0, 0xff, 1));
|
||||
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 1), make_plane_ud( 0, 0, 1, 1));
|
||||
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 2), make_plane_ud( 0, 0xff, 0, 1));
|
||||
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 3), make_plane_ud( 0, 1, 0, 1));
|
||||
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 4), make_plane_ud(0xff, 0, 0, 1));
|
||||
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 5), make_plane_ud( 1, 0, 0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define W 3
|
||||
|
||||
/* Project 'pos' to screen space (or back again), overwrite with results:
|
||||
*/
|
||||
void brw_clip_project_position(struct brw_clip_compile *c, struct brw_reg pos )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
|
||||
/* calc rhw
|
||||
*/
|
||||
brw_math_invert(p, get_element(pos, W), get_element(pos, W));
|
||||
|
||||
/* value.xyz *= value.rhw
|
||||
*/
|
||||
brw_set_access_mode(p, BRW_ALIGN_16);
|
||||
brw_MUL(p, brw_writemask(pos, BRW_WRITEMASK_XYZ), pos, brw_swizzle1(pos, W));
|
||||
brw_set_access_mode(p, BRW_ALIGN_1);
|
||||
}
|
||||
|
||||
|
||||
static void brw_clip_project_vertex( struct brw_clip_compile *c,
|
||||
struct brw_indirect vert_addr )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_reg tmp = get_tmp(c);
|
||||
|
||||
/* Fixup position. Extract from the original vertex and re-project
|
||||
* to screen space:
|
||||
*/
|
||||
brw_MOV(p, tmp, deref_4f(vert_addr, c->offset_hpos));
|
||||
brw_clip_project_position(c, tmp);
|
||||
brw_MOV(p, deref_4f(vert_addr, c->header_position_offset), tmp);
|
||||
|
||||
release_tmp(c, tmp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Interpolate between two vertices and put the result into a0.0.
|
||||
* Increment a0.0 accordingly.
|
||||
*/
|
||||
void brw_clip_interp_vertex( struct brw_clip_compile *c,
|
||||
struct brw_indirect dest_ptr,
|
||||
struct brw_indirect v0_ptr, /* from */
|
||||
struct brw_indirect v1_ptr, /* to */
|
||||
struct brw_reg t0,
|
||||
GLboolean force_edgeflag)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_reg tmp = get_tmp(c);
|
||||
GLuint i;
|
||||
|
||||
/* Just copy the vertex header:
|
||||
*/
|
||||
/*
|
||||
* After CLIP stage, only first 256 bits of the VUE are read
|
||||
* back on IGDNG, so needn't change it
|
||||
*/
|
||||
brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);
|
||||
|
||||
/* Iterate over each attribute (could be done in pairs?)
|
||||
*/
|
||||
for (i = 0; i < c->key.nr_attrs; i++) {
|
||||
GLuint delta = i*16 + 32;
|
||||
|
||||
if (c->chipset.is_igdng)
|
||||
delta = i * 16 + 32 * 3;
|
||||
|
||||
if (delta == c->offset_edgeflag) {
|
||||
if (force_edgeflag)
|
||||
brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));
|
||||
else
|
||||
brw_MOV(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta));
|
||||
}
|
||||
else {
|
||||
/* Interpolate:
|
||||
*
|
||||
* New = attr0 + t*attr1 - t*attr0
|
||||
*/
|
||||
brw_MUL(p,
|
||||
vec4(brw_null_reg()),
|
||||
deref_4f(v1_ptr, delta),
|
||||
t0);
|
||||
|
||||
brw_MAC(p,
|
||||
tmp,
|
||||
negate(deref_4f(v0_ptr, delta)),
|
||||
t0);
|
||||
|
||||
brw_ADD(p,
|
||||
deref_4f(dest_ptr, delta),
|
||||
deref_4f(v0_ptr, delta),
|
||||
tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (i & 1) {
|
||||
GLuint delta = i*16 + 32;
|
||||
|
||||
if (c->chipset.is_igdng)
|
||||
delta = i * 16 + 32 * 3;
|
||||
|
||||
brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));
|
||||
}
|
||||
|
||||
release_tmp(c, tmp);
|
||||
|
||||
/* Recreate the projected (NDC) coordinate in the new vertex
|
||||
* header:
|
||||
*/
|
||||
brw_clip_project_vertex(c, dest_ptr );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define MAX_MRF 16
|
||||
|
||||
void brw_clip_emit_vue(struct brw_clip_compile *c,
|
||||
struct brw_indirect vert,
|
||||
GLboolean allocate,
|
||||
GLboolean eot,
|
||||
GLuint header)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
GLuint start = c->last_mrf;
|
||||
|
||||
brw_clip_ff_sync(c);
|
||||
|
||||
assert(!(allocate && eot));
|
||||
|
||||
/* Cycle through mrf regs - probably futile as we have to wait for
|
||||
* the allocation response anyway. Also, the order this function
|
||||
* is invoked doesn't correspond to the order the instructions will
|
||||
* be executed, so it won't have any effect in many cases.
|
||||
*/
|
||||
#if 0
|
||||
if (start + c->nr_regs + 1 >= MAX_MRF)
|
||||
start = 0;
|
||||
|
||||
c->last_mrf = start + c->nr_regs + 1;
|
||||
#endif
|
||||
|
||||
/* Copy the vertex from vertn into m1..mN+1:
|
||||
*/
|
||||
brw_copy_from_indirect(p, brw_message_reg(start+1), vert, c->nr_regs);
|
||||
|
||||
/* Overwrite PrimType and PrimStart in the message header, for
|
||||
* each vertex in turn:
|
||||
*/
|
||||
brw_MOV(p, get_element_ud(c->reg.R0, 2), brw_imm_ud(header));
|
||||
|
||||
|
||||
/* Send each vertex as a seperate write to the urb. This
|
||||
* is different to the concept in brw_sf_emit.c, where
|
||||
* subsequent writes are used to build up a single urb
|
||||
* entry. Each of these writes instantiates a seperate
|
||||
* urb entry - (I think... what about 'allocate'?)
|
||||
*/
|
||||
brw_urb_WRITE(p,
|
||||
allocate ? c->reg.R0 : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
|
||||
start,
|
||||
c->reg.R0,
|
||||
allocate,
|
||||
1, /* used */
|
||||
c->nr_regs + 1, /* msg length */
|
||||
allocate ? 1 : 0, /* response_length */
|
||||
eot, /* eot */
|
||||
1, /* writes_complete */
|
||||
0, /* urb offset */
|
||||
BRW_URB_SWIZZLE_NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void brw_clip_kill_thread(struct brw_clip_compile *c)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
|
||||
brw_clip_ff_sync(c);
|
||||
/* Send an empty message to kill the thread and release any
|
||||
* allocated urb entry:
|
||||
*/
|
||||
brw_urb_WRITE(p,
|
||||
retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
|
||||
0,
|
||||
c->reg.R0,
|
||||
0, /* allocate */
|
||||
0, /* used */
|
||||
1, /* msg len */
|
||||
0, /* response len */
|
||||
1, /* eot */
|
||||
1, /* writes complete */
|
||||
0,
|
||||
BRW_URB_SWIZZLE_NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct brw_reg brw_clip_plane0_address( struct brw_clip_compile *c )
|
||||
{
|
||||
return brw_address(c->reg.fixed_planes);
|
||||
}
|
||||
|
||||
|
||||
struct brw_reg brw_clip_plane_stride( struct brw_clip_compile *c )
|
||||
{
|
||||
if (c->key.nr_userclip) {
|
||||
return brw_imm_uw(16);
|
||||
}
|
||||
else {
|
||||
return brw_imm_uw(4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If flatshading, distribute color from provoking vertex prior to
|
||||
* clipping.
|
||||
*/
|
||||
void brw_clip_copy_colors( struct brw_clip_compile *c,
|
||||
GLuint to, GLuint from )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
|
||||
if (c->offset_color0)
|
||||
brw_MOV(p,
|
||||
byte_offset(c->reg.vertex[to], c->offset_color0),
|
||||
byte_offset(c->reg.vertex[from], c->offset_color0));
|
||||
|
||||
if (c->offset_color1)
|
||||
brw_MOV(p,
|
||||
byte_offset(c->reg.vertex[to], c->offset_color1),
|
||||
byte_offset(c->reg.vertex[from], c->offset_color1));
|
||||
|
||||
if (c->offset_bfc0)
|
||||
brw_MOV(p,
|
||||
byte_offset(c->reg.vertex[to], c->offset_bfc0),
|
||||
byte_offset(c->reg.vertex[from], c->offset_bfc0));
|
||||
|
||||
if (c->offset_bfc1)
|
||||
brw_MOV(p,
|
||||
byte_offset(c->reg.vertex[to], c->offset_bfc1),
|
||||
byte_offset(c->reg.vertex[from], c->offset_bfc1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void brw_clip_init_clipmask( struct brw_clip_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_reg incoming = get_element_ud(c->reg.R0, 2);
|
||||
|
||||
/* Shift so that lowest outcode bit is rightmost:
|
||||
*/
|
||||
brw_SHR(p, c->reg.planemask, incoming, brw_imm_ud(26));
|
||||
|
||||
if (c->key.nr_userclip) {
|
||||
struct brw_reg tmp = retype(vec1(get_tmp(c)), BRW_REGISTER_TYPE_UD);
|
||||
|
||||
/* Rearrange userclip outcodes so that they come directly after
|
||||
* the fixed plane bits.
|
||||
*/
|
||||
brw_AND(p, tmp, incoming, brw_imm_ud(0x3f<<14));
|
||||
brw_SHR(p, tmp, tmp, brw_imm_ud(8));
|
||||
brw_OR(p, c->reg.planemask, c->reg.planemask, tmp);
|
||||
|
||||
release_tmp(c, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void brw_clip_ff_sync(struct brw_clip_compile *c)
|
||||
{
|
||||
if (c->need_ff_sync) {
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *need_ff_sync;
|
||||
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
|
||||
brw_AND(p, brw_null_reg(), c->reg.ff_sync, brw_imm_ud(0x1));
|
||||
need_ff_sync = brw_IF(p, BRW_EXECUTE_1);
|
||||
{
|
||||
brw_OR(p, c->reg.ff_sync, c->reg.ff_sync, brw_imm_ud(0x1));
|
||||
brw_ff_sync(p,
|
||||
c->reg.R0,
|
||||
0,
|
||||
c->reg.R0,
|
||||
1,
|
||||
1, /* used */
|
||||
1, /* msg length */
|
||||
1, /* response length */
|
||||
0, /* eot */
|
||||
1, /* write compelete */
|
||||
0, /* urb offset */
|
||||
BRW_URB_SWIZZLE_NONE);
|
||||
}
|
||||
brw_ENDIF(p, need_ff_sync);
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void brw_clip_init_ff_sync(struct brw_clip_compile *c)
|
||||
{
|
||||
if (c->need_ff_sync) {
|
||||
struct brw_compile *p = &c->func;
|
||||
|
||||
brw_MOV(p, c->reg.ff_sync, brw_imm_ud(0));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "util/u_simple_list.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_draw.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_winsys.h"
|
||||
#include "brw_screen.h"
|
||||
|
||||
|
||||
static void brw_destroy_context( struct pipe_context *pipe )
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
int i;
|
||||
|
||||
brw_context_flush( brw );
|
||||
brw_batchbuffer_free( brw->batch );
|
||||
brw_destroy_state(brw);
|
||||
|
||||
brw_draw_cleanup( brw );
|
||||
|
||||
brw_pipe_blend_cleanup( brw );
|
||||
brw_pipe_depth_stencil_cleanup( brw );
|
||||
brw_pipe_framebuffer_cleanup( brw );
|
||||
brw_pipe_flush_cleanup( brw );
|
||||
brw_pipe_misc_cleanup( brw );
|
||||
brw_pipe_query_cleanup( brw );
|
||||
brw_pipe_rast_cleanup( brw );
|
||||
brw_pipe_sampler_cleanup( brw );
|
||||
brw_pipe_shader_cleanup( brw );
|
||||
brw_pipe_vertex_cleanup( brw );
|
||||
brw_pipe_clear_cleanup( brw );
|
||||
|
||||
brw_hw_cc_cleanup( brw );
|
||||
|
||||
|
||||
FREE(brw->wm.compile_data);
|
||||
|
||||
for (i = 0; i < brw->curr.fb.nr_cbufs; i++)
|
||||
pipe_surface_reference(&brw->curr.fb.cbufs[i], NULL);
|
||||
brw->curr.fb.nr_cbufs = 0;
|
||||
pipe_surface_reference(&brw->curr.fb.zsbuf, NULL);
|
||||
|
||||
bo_reference(&brw->curbe.curbe_bo, NULL);
|
||||
bo_reference(&brw->vs.prog_bo, NULL);
|
||||
bo_reference(&brw->vs.state_bo, NULL);
|
||||
bo_reference(&brw->vs.bind_bo, NULL);
|
||||
bo_reference(&brw->gs.prog_bo, NULL);
|
||||
bo_reference(&brw->gs.state_bo, NULL);
|
||||
bo_reference(&brw->clip.prog_bo, NULL);
|
||||
bo_reference(&brw->clip.state_bo, NULL);
|
||||
bo_reference(&brw->clip.vp_bo, NULL);
|
||||
bo_reference(&brw->sf.prog_bo, NULL);
|
||||
bo_reference(&brw->sf.state_bo, NULL);
|
||||
bo_reference(&brw->sf.vp_bo, NULL);
|
||||
|
||||
for (i = 0; i < Elements(brw->wm.sdc_bo); i++)
|
||||
bo_reference(&brw->wm.sdc_bo[i], NULL);
|
||||
|
||||
bo_reference(&brw->wm.bind_bo, NULL);
|
||||
|
||||
for (i = 0; i < Elements(brw->wm.surf_bo); i++)
|
||||
bo_reference(&brw->wm.surf_bo[i], NULL);
|
||||
|
||||
bo_reference(&brw->wm.sampler_bo, NULL);
|
||||
bo_reference(&brw->wm.prog_bo, NULL);
|
||||
bo_reference(&brw->wm.state_bo, NULL);
|
||||
}
|
||||
|
||||
|
||||
struct pipe_context *brw_create_context(struct pipe_screen *screen)
|
||||
{
|
||||
struct brw_context *brw = (struct brw_context *) CALLOC_STRUCT(brw_context);
|
||||
|
||||
if (!brw) {
|
||||
debug_printf("%s: failed to alloc context\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
brw->base.screen = screen;
|
||||
brw->base.destroy = brw_destroy_context;
|
||||
brw->sws = brw_screen(screen)->sws;
|
||||
brw->chipset = brw_screen(screen)->chipset;
|
||||
|
||||
brw_pipe_blend_init( brw );
|
||||
brw_pipe_depth_stencil_init( brw );
|
||||
brw_pipe_framebuffer_init( brw );
|
||||
brw_pipe_flush_init( brw );
|
||||
brw_pipe_misc_init( brw );
|
||||
brw_pipe_query_init( brw );
|
||||
brw_pipe_rast_init( brw );
|
||||
brw_pipe_sampler_init( brw );
|
||||
brw_pipe_shader_init( brw );
|
||||
brw_pipe_vertex_init( brw );
|
||||
brw_pipe_clear_init( brw );
|
||||
|
||||
brw_hw_cc_init( brw );
|
||||
|
||||
brw_init_state( brw );
|
||||
brw_draw_init( brw );
|
||||
|
||||
brw->state.dirty.mesa = ~0;
|
||||
brw->state.dirty.brw = ~0;
|
||||
|
||||
brw->flags.always_emit_state = 0;
|
||||
|
||||
make_empty_list(&brw->query.active_head);
|
||||
|
||||
brw->batch = brw_batchbuffer_alloc( brw->sws, brw->chipset );
|
||||
if (brw->batch == NULL)
|
||||
goto fail;
|
||||
|
||||
return &brw->base;
|
||||
|
||||
fail:
|
||||
if (brw->batch)
|
||||
brw_batchbuffer_free( brw->batch );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,853 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BRWCONTEXT_INC
|
||||
#define BRWCONTEXT_INC
|
||||
|
||||
#include "brw_structs.h"
|
||||
#include "brw_winsys.h"
|
||||
#include "brw_reg.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "tgsi/tgsi_scan.h"
|
||||
|
||||
|
||||
/* Glossary:
|
||||
*
|
||||
* URB - uniform resource buffer. A mid-sized buffer which is
|
||||
* partitioned between the fixed function units and used for passing
|
||||
* values (vertices, primitives, constants) between them.
|
||||
*
|
||||
* CURBE - constant URB entry. An urb region (entry) used to hold
|
||||
* constant values which the fixed function units can be instructed to
|
||||
* preload into the GRF when spawning a thread.
|
||||
*
|
||||
* VUE - vertex URB entry. An urb entry holding a vertex and usually
|
||||
* a vertex header. The header contains control information and
|
||||
* things like primitive type, Begin/end flags and clip codes.
|
||||
*
|
||||
* PUE - primitive URB entry. An urb entry produced by the setup (SF)
|
||||
* unit holding rasterization and interpolation parameters.
|
||||
*
|
||||
* GRF - general register file. One of several register files
|
||||
* addressable by programmed threads. The inputs (r0, payload, curbe,
|
||||
* urb) of the thread are preloaded to this area before the thread is
|
||||
* spawned. The registers are individually 8 dwords wide and suitable
|
||||
* for general usage. Registers holding thread input values are not
|
||||
* special and may be overwritten.
|
||||
*
|
||||
* MRF - message register file. Threads communicate (and terminate)
|
||||
* by sending messages. Message parameters are placed in contiguous
|
||||
* MRF registers. All program output is via these messages. URB
|
||||
* entries are populated by sending a message to the shared URB
|
||||
* function containing the new data, together with a control word,
|
||||
* often an unmodified copy of R0.
|
||||
*
|
||||
* R0 - GRF register 0. Typically holds control information used when
|
||||
* sending messages to other threads.
|
||||
*
|
||||
* EU or GEN4 EU: The name of the programmable subsystem of the
|
||||
* i965 hardware. Threads are executed by the EU, the registers
|
||||
* described above are part of the EU architecture.
|
||||
*
|
||||
* Fixed function units:
|
||||
*
|
||||
* CS - Command streamer. Notional first unit, little software
|
||||
* interaction. Holds the URB entries used for constant data, ie the
|
||||
* CURBEs.
|
||||
*
|
||||
* VF/VS - Vertex Fetch / Vertex Shader. The fixed function part of
|
||||
* this unit is responsible for pulling vertices out of vertex buffers
|
||||
* in vram and injecting them into the processing pipe as VUEs. If
|
||||
* enabled, it first passes them to a VS thread which is a good place
|
||||
* for the driver to implement any active vertex shader.
|
||||
*
|
||||
* GS - Geometry Shader. This corresponds to a new DX10 concept. If
|
||||
* enabled, incoming strips etc are passed to GS threads in individual
|
||||
* line/triangle/point units. The GS thread may perform arbitary
|
||||
* computation and emit whatever primtives with whatever vertices it
|
||||
* chooses. This makes GS an excellent place to implement GL's
|
||||
* unfilled polygon modes, though of course it is capable of much
|
||||
* more. Additionally, GS is used to translate away primitives not
|
||||
* handled by latter units, including Quads and Lineloops.
|
||||
*
|
||||
* CS - Clipper. Mesa's clipping algorithms are imported to run on
|
||||
* this unit. The fixed function part performs cliptesting against
|
||||
* the 6 fixed clipplanes and makes decisions on whether or not the
|
||||
* incoming primitive needs to be passed to a thread for clipping.
|
||||
* User clip planes are handled via cooperation with the VS thread.
|
||||
*
|
||||
* SF - Strips Fans or Setup: Triangles are prepared for
|
||||
* rasterization. Interpolation coefficients are calculated.
|
||||
* Flatshading and two-side lighting usually performed here.
|
||||
*
|
||||
* WM - Windower. Interpolation of vertex attributes performed here.
|
||||
* Fragment shader implemented here. SIMD aspects of EU taken full
|
||||
* advantage of, as pixels are processed in blocks of 16.
|
||||
*
|
||||
* CC - Color Calculator. No EU threads associated with this unit.
|
||||
* Handles blending and (presumably) depth and stencil testing.
|
||||
*/
|
||||
|
||||
#define BRW_MAX_CURBE (32*16)
|
||||
|
||||
struct brw_context;
|
||||
|
||||
struct brw_depth_stencil_state {
|
||||
/* Precalculated hardware state:
|
||||
*/
|
||||
struct brw_cc0 cc0;
|
||||
struct brw_cc1 cc1;
|
||||
struct brw_cc2 cc2;
|
||||
struct brw_cc3 cc3;
|
||||
struct brw_cc7 cc7;
|
||||
|
||||
unsigned iz_lookup;
|
||||
};
|
||||
|
||||
|
||||
struct brw_blend_state {
|
||||
/* Precalculated hardware state:
|
||||
*/
|
||||
struct brw_cc2 cc2;
|
||||
struct brw_cc3 cc3;
|
||||
struct brw_cc5 cc5;
|
||||
struct brw_cc6 cc6;
|
||||
|
||||
struct brw_surf_ss0 ss0;
|
||||
};
|
||||
|
||||
|
||||
struct brw_rasterizer_state;
|
||||
|
||||
struct brw_immediate_data {
|
||||
unsigned nr;
|
||||
float (*data)[4];
|
||||
};
|
||||
|
||||
struct brw_vertex_shader {
|
||||
const struct tgsi_token *tokens;
|
||||
struct brw_winsys_buffer *const_buffer; /** Program constant buffer/surface */
|
||||
|
||||
struct tgsi_shader_info info;
|
||||
struct brw_immediate_data immediates;
|
||||
|
||||
GLuint has_flow_control:1;
|
||||
GLuint use_const_buffer:1;
|
||||
|
||||
/* Offsets of special vertex shader outputs required for clipping.
|
||||
*/
|
||||
GLuint output_hpos:6; /* not always zero? */
|
||||
GLuint output_color0:6;
|
||||
GLuint output_color1:6;
|
||||
GLuint output_bfc0:6;
|
||||
GLuint output_bfc1:6;
|
||||
GLuint output_edgeflag:6;
|
||||
|
||||
unsigned id;
|
||||
};
|
||||
|
||||
struct brw_fs_signature {
|
||||
GLuint nr_inputs;
|
||||
struct {
|
||||
GLuint interp:3; /* TGSI_INTERPOLATE_x */
|
||||
GLuint semantic:5; /* TGSI_SEMANTIC_x */
|
||||
GLuint semantic_index:24;
|
||||
} input[PIPE_MAX_SHADER_INPUTS];
|
||||
};
|
||||
|
||||
#define brw_fs_signature_size(s) (offsetof(struct brw_fs_signature, input) + \
|
||||
((s)->nr_inputs * sizeof (s)->input[0]))
|
||||
|
||||
|
||||
struct brw_fragment_shader {
|
||||
const struct tgsi_token *tokens;
|
||||
struct tgsi_shader_info info;
|
||||
|
||||
struct brw_fs_signature signature;
|
||||
struct brw_immediate_data immediates;
|
||||
|
||||
unsigned iz_lookup;
|
||||
/*unsigned wm_lookup;*/
|
||||
|
||||
unsigned uses_depth:1;
|
||||
unsigned has_flow_control:1;
|
||||
|
||||
unsigned id;
|
||||
struct brw_winsys_buffer *const_buffer; /** Program constant buffer/surface */
|
||||
GLboolean use_const_buffer;
|
||||
};
|
||||
|
||||
|
||||
struct brw_sampler {
|
||||
struct brw_ss0 ss0;
|
||||
struct brw_ss1 ss1;
|
||||
float border_color[4];
|
||||
struct brw_ss3 ss3;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define PIPE_NEW_DEPTH_STENCIL_ALPHA 0x1
|
||||
#define PIPE_NEW_RAST 0x2
|
||||
#define PIPE_NEW_BLEND 0x4
|
||||
#define PIPE_NEW_VIEWPORT 0x8
|
||||
#define PIPE_NEW_SAMPLERS 0x10
|
||||
#define PIPE_NEW_VERTEX_BUFFER 0x20
|
||||
#define PIPE_NEW_VERTEX_ELEMENT 0x40
|
||||
#define PIPE_NEW_FRAGMENT_SHADER 0x80
|
||||
#define PIPE_NEW_VERTEX_SHADER 0x100
|
||||
#define PIPE_NEW_FRAGMENT_CONSTANTS 0x200
|
||||
#define PIPE_NEW_VERTEX_CONSTANTS 0x400
|
||||
#define PIPE_NEW_CLIP 0x800
|
||||
#define PIPE_NEW_INDEX_BUFFER 0x1000
|
||||
#define PIPE_NEW_INDEX_RANGE 0x2000
|
||||
#define PIPE_NEW_BLEND_COLOR 0x4000
|
||||
#define PIPE_NEW_POLYGON_STIPPLE 0x8000
|
||||
#define PIPE_NEW_FRAMEBUFFER_DIMENSIONS 0x10000
|
||||
#define PIPE_NEW_DEPTH_BUFFER 0x20000
|
||||
#define PIPE_NEW_COLOR_BUFFERS 0x40000
|
||||
#define PIPE_NEW_QUERY 0x80000
|
||||
#define PIPE_NEW_SCISSOR 0x100000
|
||||
#define PIPE_NEW_BOUND_TEXTURES 0x200000
|
||||
#define PIPE_NEW_NR_CBUFS 0x400000
|
||||
#define PIPE_NEW_FRAGMENT_SIGNATURE 0x800000
|
||||
|
||||
|
||||
|
||||
#define BRW_NEW_URB_FENCE 0x1
|
||||
#define BRW_NEW_FRAGMENT_PROGRAM 0x2
|
||||
#define BRW_NEW_VERTEX_PROGRAM 0x4
|
||||
#define BRW_NEW_INPUT_DIMENSIONS 0x8
|
||||
#define BRW_NEW_CURBE_OFFSETS 0x10
|
||||
#define BRW_NEW_REDUCED_PRIMITIVE 0x20
|
||||
#define BRW_NEW_PRIMITIVE 0x40
|
||||
#define BRW_NEW_CONTEXT 0x80
|
||||
#define BRW_NEW_WM_INPUT_DIMENSIONS 0x100
|
||||
#define BRW_NEW_PSP 0x800
|
||||
#define BRW_NEW_WM_SURFACES 0x1000
|
||||
#define BRW_NEW_xxx 0x2000 /* was FENCE */
|
||||
#define BRW_NEW_INDICES 0x4000
|
||||
|
||||
/**
|
||||
* Used for any batch entry with a relocated pointer that will be used
|
||||
* by any 3D rendering. Need to re-emit these fresh in each
|
||||
* batchbuffer as the referenced buffers may be relocated in the
|
||||
* meantime.
|
||||
*/
|
||||
#define BRW_NEW_BATCH 0x10000
|
||||
#define BRW_NEW_NR_WM_SURFACES 0x40000
|
||||
#define BRW_NEW_NR_VS_SURFACES 0x80000
|
||||
#define BRW_NEW_INDEX_BUFFER 0x100000
|
||||
|
||||
struct brw_state_flags {
|
||||
/** State update flags signalled by mesa internals */
|
||||
GLuint mesa;
|
||||
/**
|
||||
* State update flags signalled as the result of brw_tracked_state updates
|
||||
*/
|
||||
GLuint brw;
|
||||
/** State update flags signalled by brw_state_cache.c searches */
|
||||
GLuint cache;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Data about a particular attempt to compile a program. Note that
|
||||
* there can be many of these, each in a different GL state
|
||||
* corresponding to a different brw_wm_prog_key struct, with different
|
||||
* compiled programs:
|
||||
*/
|
||||
struct brw_wm_prog_data {
|
||||
GLuint curb_read_length;
|
||||
GLuint urb_read_length;
|
||||
|
||||
GLuint first_curbe_grf;
|
||||
GLuint total_grf;
|
||||
GLuint total_scratch;
|
||||
|
||||
GLuint nr_params; /**< number of float params/constants */
|
||||
GLboolean error;
|
||||
|
||||
/* Pointer to tracked values (only valid once
|
||||
* _mesa_load_state_parameters has been called at runtime).
|
||||
*/
|
||||
const GLfloat *param[BRW_MAX_CURBE];
|
||||
};
|
||||
|
||||
struct brw_sf_prog_data {
|
||||
GLuint urb_read_length;
|
||||
GLuint total_grf;
|
||||
|
||||
/* Each vertex may have upto 12 attributes, 4 components each,
|
||||
* except WPOS which requires only 2. (11*4 + 2) == 44 ==> 11
|
||||
* rows.
|
||||
*
|
||||
* Actually we use 4 for each, so call it 12 rows.
|
||||
*/
|
||||
GLuint urb_entry_size;
|
||||
};
|
||||
|
||||
|
||||
struct brw_clip_prog_data;
|
||||
|
||||
struct brw_gs_prog_data {
|
||||
GLuint urb_read_length;
|
||||
GLuint total_grf;
|
||||
};
|
||||
|
||||
struct brw_vs_prog_data {
|
||||
GLuint curb_read_length;
|
||||
GLuint urb_read_length;
|
||||
GLuint total_grf;
|
||||
|
||||
GLuint nr_outputs;
|
||||
GLuint nr_inputs;
|
||||
|
||||
GLuint nr_params; /**< number of TGSI_FILE_CONSTANT's */
|
||||
|
||||
GLuint output_edgeflag;
|
||||
|
||||
GLboolean writes_psiz;
|
||||
|
||||
/* Used for calculating urb partitions:
|
||||
*/
|
||||
GLuint urb_entry_size;
|
||||
};
|
||||
|
||||
|
||||
/* Size == 0 if output either not written, or always [0,0,0,1]
|
||||
*/
|
||||
struct brw_vs_ouput_sizes {
|
||||
GLubyte output_size[PIPE_MAX_SHADER_OUTPUTS];
|
||||
};
|
||||
|
||||
|
||||
/** Number of texture sampler units */
|
||||
#define BRW_MAX_TEX_UNIT 16
|
||||
|
||||
/** Max number of render targets in a shader */
|
||||
#define BRW_MAX_DRAW_BUFFERS 4
|
||||
|
||||
/**
|
||||
* Size of our surface binding table for the WM.
|
||||
* This contains pointers to the drawing surfaces and current texture
|
||||
* objects and shader constant buffers (+2).
|
||||
*/
|
||||
#define BRW_WM_MAX_SURF (BRW_MAX_DRAW_BUFFERS + BRW_MAX_TEX_UNIT + 1)
|
||||
|
||||
/**
|
||||
* Helpers to convert drawing buffers, textures and constant buffers
|
||||
* to surface binding table indexes, for WM.
|
||||
*/
|
||||
#define BTI_COLOR_BUF(d) (d)
|
||||
#define BTI_FRAGMENT_CONSTANTS (BRW_MAX_DRAW_BUFFERS)
|
||||
#define BTI_TEXTURE(t) (BRW_MAX_DRAW_BUFFERS + 1 + (t))
|
||||
|
||||
/**
|
||||
* Size of surface binding table for the VS.
|
||||
* Only one constant buffer for now.
|
||||
*/
|
||||
#define BRW_VS_MAX_SURF 1
|
||||
|
||||
/**
|
||||
* Only a VS constant buffer
|
||||
*/
|
||||
#define SURF_INDEX_VERT_CONST_BUFFER 0
|
||||
|
||||
|
||||
/* Bit of a hack to align these with the winsys buffer_data_type enum.
|
||||
*/
|
||||
enum brw_cache_id {
|
||||
BRW_CC_VP = BRW_DATA_GS_CC_VP,
|
||||
BRW_CC_UNIT = BRW_DATA_GS_CC_UNIT,
|
||||
BRW_WM_PROG = BRW_DATA_GS_WM_PROG,
|
||||
BRW_SAMPLER_DEFAULT_COLOR = BRW_DATA_GS_SAMPLER_DEFAULT_COLOR,
|
||||
BRW_SAMPLER = BRW_DATA_GS_SAMPLER,
|
||||
BRW_WM_UNIT = BRW_DATA_GS_WM_UNIT,
|
||||
BRW_SF_PROG = BRW_DATA_GS_SF_PROG,
|
||||
BRW_SF_VP = BRW_DATA_GS_SF_VP,
|
||||
BRW_SF_UNIT = BRW_DATA_GS_SF_UNIT,
|
||||
BRW_VS_UNIT = BRW_DATA_GS_VS_UNIT,
|
||||
BRW_VS_PROG = BRW_DATA_GS_VS_PROG,
|
||||
BRW_GS_UNIT = BRW_DATA_GS_GS_UNIT,
|
||||
BRW_GS_PROG = BRW_DATA_GS_GS_PROG,
|
||||
BRW_CLIP_VP = BRW_DATA_GS_CLIP_VP,
|
||||
BRW_CLIP_UNIT = BRW_DATA_GS_CLIP_UNIT,
|
||||
BRW_CLIP_PROG = BRW_DATA_GS_CLIP_PROG,
|
||||
BRW_SS_SURFACE = BRW_DATA_SS_SURFACE,
|
||||
BRW_SS_SURF_BIND = BRW_DATA_SS_SURF_BIND,
|
||||
|
||||
BRW_MAX_CACHE
|
||||
};
|
||||
|
||||
struct brw_cache_item {
|
||||
/**
|
||||
* Effectively part of the key, cache_id identifies what kind of state
|
||||
* buffer is involved, and also which brw->state.dirty.cache flag should
|
||||
* be set when this cache item is chosen.
|
||||
*/
|
||||
enum brw_cache_id cache_id;
|
||||
/** 32-bit hash of the key data */
|
||||
GLuint hash;
|
||||
GLuint key_size; /* for variable-sized keys */
|
||||
const void *key;
|
||||
struct brw_winsys_reloc *relocs;
|
||||
GLuint nr_relocs;
|
||||
|
||||
struct brw_winsys_buffer *bo;
|
||||
GLuint data_size;
|
||||
|
||||
struct brw_cache_item *next;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct brw_cache {
|
||||
struct brw_context *brw;
|
||||
struct brw_winsys_screen *sws;
|
||||
|
||||
struct brw_cache_item **items;
|
||||
GLuint size, n_items;
|
||||
|
||||
enum brw_buffer_type buffer_type;
|
||||
|
||||
GLuint key_size[BRW_MAX_CACHE]; /* for fixed-size keys */
|
||||
GLuint aux_size[BRW_MAX_CACHE];
|
||||
char *name[BRW_MAX_CACHE];
|
||||
|
||||
|
||||
/* Record of the last BOs chosen for each cache_id. Used to set
|
||||
* brw->state.dirty.cache when a new cache item is chosen.
|
||||
*/
|
||||
struct brw_winsys_buffer *last_bo[BRW_MAX_CACHE];
|
||||
};
|
||||
|
||||
|
||||
struct brw_tracked_state {
|
||||
struct brw_state_flags dirty;
|
||||
int (*prepare)( struct brw_context *brw );
|
||||
int (*emit)( struct brw_context *brw );
|
||||
};
|
||||
|
||||
/* Flags for brw->state.cache.
|
||||
*/
|
||||
#define CACHE_NEW_CC_VP (1<<BRW_CC_VP)
|
||||
#define CACHE_NEW_CC_UNIT (1<<BRW_CC_UNIT)
|
||||
#define CACHE_NEW_WM_PROG (1<<BRW_WM_PROG)
|
||||
#define CACHE_NEW_SAMPLER_DEFAULT_COLOR (1<<BRW_SAMPLER_DEFAULT_COLOR)
|
||||
#define CACHE_NEW_SAMPLER (1<<BRW_SAMPLER)
|
||||
#define CACHE_NEW_WM_UNIT (1<<BRW_WM_UNIT)
|
||||
#define CACHE_NEW_SF_PROG (1<<BRW_SF_PROG)
|
||||
#define CACHE_NEW_SF_VP (1<<BRW_SF_VP)
|
||||
#define CACHE_NEW_SF_UNIT (1<<BRW_SF_UNIT)
|
||||
#define CACHE_NEW_VS_UNIT (1<<BRW_VS_UNIT)
|
||||
#define CACHE_NEW_VS_PROG (1<<BRW_VS_PROG)
|
||||
#define CACHE_NEW_GS_UNIT (1<<BRW_GS_UNIT)
|
||||
#define CACHE_NEW_GS_PROG (1<<BRW_GS_PROG)
|
||||
#define CACHE_NEW_CLIP_VP (1<<BRW_CLIP_VP)
|
||||
#define CACHE_NEW_CLIP_UNIT (1<<BRW_CLIP_UNIT)
|
||||
#define CACHE_NEW_CLIP_PROG (1<<BRW_CLIP_PROG)
|
||||
#define CACHE_NEW_SURFACE (1<<BRW_SS_SURFACE)
|
||||
#define CACHE_NEW_SURF_BIND (1<<BRW_SS_SURF_BIND)
|
||||
|
||||
struct brw_cached_batch_item {
|
||||
struct header *header;
|
||||
GLuint sz;
|
||||
struct brw_cached_batch_item *next;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Protect against a future where VERT_ATTRIB_MAX > 32. Wouldn't life
|
||||
* be easier if C allowed arrays of packed elements?
|
||||
*/
|
||||
#define VS_INPUT_BITMASK_DWORDS ((PIPE_MAX_SHADER_INPUTS+31)/32)
|
||||
|
||||
|
||||
|
||||
|
||||
struct brw_vertex_info {
|
||||
GLuint sizes[VS_INPUT_BITMASK_DWORDS * 2]; /* sizes:2[VERT_ATTRIB_MAX] */
|
||||
};
|
||||
|
||||
|
||||
struct brw_query_object {
|
||||
/** Doubly linked list of active query objects in the context. */
|
||||
struct brw_query_object *prev, *next;
|
||||
|
||||
/** Last query BO associated with this query. */
|
||||
struct brw_winsys_buffer *bo;
|
||||
/** First index in bo with query data for this object. */
|
||||
int first_index;
|
||||
/** Last index in bo with query data for this object. */
|
||||
int last_index;
|
||||
|
||||
/* Total count of pixels from previous BOs */
|
||||
uint64_t result;
|
||||
};
|
||||
|
||||
#define CC_RELOC_VP 0
|
||||
|
||||
|
||||
/**
|
||||
* brw_context is derived from pipe_context
|
||||
*/
|
||||
struct brw_context
|
||||
{
|
||||
struct pipe_context base;
|
||||
struct brw_chipset chipset;
|
||||
|
||||
struct brw_winsys_screen *sws;
|
||||
|
||||
struct brw_batchbuffer *batch;
|
||||
|
||||
GLuint primitive;
|
||||
GLuint reduced_primitive;
|
||||
|
||||
/* Active state from the state tracker:
|
||||
*/
|
||||
struct {
|
||||
struct brw_vertex_shader *vertex_shader;
|
||||
struct brw_fragment_shader *fragment_shader;
|
||||
const struct brw_blend_state *blend;
|
||||
const struct brw_rasterizer_state *rast;
|
||||
const struct brw_depth_stencil_state *zstencil;
|
||||
|
||||
const struct brw_sampler *sampler[PIPE_MAX_SAMPLERS];
|
||||
unsigned num_samplers;
|
||||
|
||||
struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
|
||||
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
|
||||
struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
|
||||
unsigned num_vertex_elements;
|
||||
unsigned num_textures;
|
||||
unsigned num_vertex_buffers;
|
||||
|
||||
struct pipe_scissor_state scissor;
|
||||
struct pipe_viewport_state viewport;
|
||||
struct pipe_framebuffer_state fb;
|
||||
struct pipe_clip_state ucp;
|
||||
struct pipe_buffer *vertex_constants;
|
||||
struct pipe_buffer *fragment_constants;
|
||||
|
||||
struct brw_blend_constant_color bcc;
|
||||
struct brw_polygon_stipple bps;
|
||||
struct brw_cc_viewport ccv;
|
||||
|
||||
/**
|
||||
* Index buffer for this draw_prims call.
|
||||
*
|
||||
* Updates are signaled by PIPE_NEW_INDEX_BUFFER.
|
||||
*/
|
||||
struct pipe_buffer *index_buffer;
|
||||
unsigned index_size;
|
||||
|
||||
/* Updates are signalled by PIPE_NEW_INDEX_RANGE:
|
||||
*/
|
||||
unsigned min_index;
|
||||
unsigned max_index;
|
||||
|
||||
} curr;
|
||||
|
||||
struct {
|
||||
struct brw_state_flags dirty;
|
||||
|
||||
/**
|
||||
* List of buffers accumulated in brw_validate_state to receive
|
||||
* dri_bo_check_aperture treatment before exec, so we can know if we
|
||||
* should flush the batch and try again before emitting primitives.
|
||||
*
|
||||
* This can be a fixed number as we only have a limited number of
|
||||
* objects referenced from the batchbuffer in a primitive emit,
|
||||
* consisting of the vertex buffers, pipelined state pointers,
|
||||
* the CURBE, the depth buffer, and a query BO.
|
||||
*/
|
||||
struct brw_winsys_buffer *validated_bos[PIPE_MAX_SHADER_INPUTS + 16];
|
||||
int validated_bo_count;
|
||||
} state;
|
||||
|
||||
struct brw_cache cache; /** non-surface items */
|
||||
struct brw_cache surface_cache; /* surface items */
|
||||
struct brw_cached_batch_item *cached_batch_items;
|
||||
|
||||
struct {
|
||||
struct u_upload_mgr *upload_vertex;
|
||||
struct u_upload_mgr *upload_index;
|
||||
|
||||
/* Information on uploaded vertex buffers:
|
||||
*/
|
||||
struct {
|
||||
unsigned stride; /* in bytes between successive vertices */
|
||||
unsigned offset; /* in bytes, of first vertex in bo */
|
||||
unsigned vertex_count; /* count of valid vertices which may be accessed */
|
||||
struct brw_winsys_buffer *bo;
|
||||
} vb[PIPE_MAX_ATTRIBS];
|
||||
|
||||
unsigned nr_vb; /* currently the same as curr.num_vertex_buffers */
|
||||
} vb;
|
||||
|
||||
struct {
|
||||
/* Updates to these fields are signaled by BRW_NEW_INDEX_BUFFER. */
|
||||
struct brw_winsys_buffer *bo;
|
||||
unsigned int offset;
|
||||
unsigned int size;
|
||||
/* Offset to index buffer index to use in CMD_3D_PRIM so that we can
|
||||
* avoid re-uploading the IB packet over and over if we're actually
|
||||
* referencing the same index buffer.
|
||||
*/
|
||||
unsigned int start_vertex_offset;
|
||||
} ib;
|
||||
|
||||
|
||||
/* BRW_NEW_URB_ALLOCATIONS:
|
||||
*/
|
||||
struct {
|
||||
GLuint vsize; /* vertex size plus header in urb registers */
|
||||
GLuint csize; /* constant buffer size in urb registers */
|
||||
GLuint sfsize; /* setup data size in urb registers */
|
||||
|
||||
GLboolean constrained;
|
||||
|
||||
GLuint nr_vs_entries;
|
||||
GLuint nr_gs_entries;
|
||||
GLuint nr_clip_entries;
|
||||
GLuint nr_sf_entries;
|
||||
GLuint nr_cs_entries;
|
||||
|
||||
GLuint vs_start;
|
||||
GLuint gs_start;
|
||||
GLuint clip_start;
|
||||
GLuint sf_start;
|
||||
GLuint cs_start;
|
||||
} urb;
|
||||
|
||||
|
||||
/* BRW_NEW_CURBE_OFFSETS:
|
||||
*/
|
||||
struct {
|
||||
GLuint wm_start; /**< pos of first wm const in CURBE buffer */
|
||||
GLuint wm_size; /**< number of float[4] consts, multiple of 16 */
|
||||
GLuint clip_start;
|
||||
GLuint clip_size;
|
||||
GLuint vs_start;
|
||||
GLuint vs_size;
|
||||
GLuint total_size;
|
||||
|
||||
struct brw_winsys_buffer *curbe_bo;
|
||||
/** Offset within curbe_bo of space for current curbe entry */
|
||||
GLuint curbe_offset;
|
||||
/** Offset within curbe_bo of space for next curbe entry */
|
||||
GLuint curbe_next_offset;
|
||||
|
||||
GLfloat *last_buf;
|
||||
GLuint last_bufsz;
|
||||
/**
|
||||
* Whether we should create a new bo instead of reusing the old one
|
||||
* (if we just dispatch the batch pointing at the old one.
|
||||
*/
|
||||
GLboolean need_new_bo;
|
||||
} curbe;
|
||||
|
||||
struct {
|
||||
struct brw_vs_prog_data *prog_data;
|
||||
|
||||
struct brw_winsys_buffer *prog_bo;
|
||||
struct brw_winsys_buffer *state_bo;
|
||||
|
||||
/** Binding table of pointers to surf_bo entries */
|
||||
struct brw_winsys_buffer *bind_bo;
|
||||
struct brw_winsys_buffer *surf_bo[BRW_VS_MAX_SURF];
|
||||
GLuint nr_surfaces;
|
||||
} vs;
|
||||
|
||||
struct {
|
||||
struct brw_gs_prog_data *prog_data;
|
||||
|
||||
GLboolean prog_active;
|
||||
struct brw_winsys_buffer *prog_bo;
|
||||
struct brw_winsys_buffer *state_bo;
|
||||
} gs;
|
||||
|
||||
struct {
|
||||
struct brw_clip_prog_data *prog_data;
|
||||
|
||||
struct brw_winsys_buffer *prog_bo;
|
||||
struct brw_winsys_buffer *state_bo;
|
||||
struct brw_winsys_buffer *vp_bo;
|
||||
} clip;
|
||||
|
||||
|
||||
struct {
|
||||
struct brw_sf_prog_data *prog_data;
|
||||
|
||||
struct brw_winsys_buffer *prog_bo;
|
||||
struct brw_winsys_buffer *state_bo;
|
||||
struct brw_winsys_buffer *vp_bo;
|
||||
} sf;
|
||||
|
||||
struct {
|
||||
struct brw_wm_prog_data *prog_data;
|
||||
struct brw_wm_compile *compile_data;
|
||||
|
||||
/** Input sizes, calculated from active vertex program.
|
||||
* One bit per fragment program input attribute.
|
||||
*/
|
||||
/*GLbitfield input_size_masks[4];*/
|
||||
|
||||
/** Array of surface default colors (texture border color) */
|
||||
struct brw_winsys_buffer *sdc_bo[BRW_MAX_TEX_UNIT];
|
||||
|
||||
GLuint render_surf;
|
||||
GLuint nr_surfaces;
|
||||
|
||||
GLuint max_threads;
|
||||
struct brw_winsys_buffer *scratch_bo;
|
||||
|
||||
GLuint sampler_count;
|
||||
struct brw_winsys_buffer *sampler_bo;
|
||||
|
||||
/** Binding table of pointers to surf_bo entries */
|
||||
struct brw_winsys_buffer *bind_bo;
|
||||
struct brw_winsys_buffer *surf_bo[BRW_WM_MAX_SURF];
|
||||
|
||||
struct brw_winsys_buffer *prog_bo;
|
||||
struct brw_winsys_buffer *state_bo;
|
||||
} wm;
|
||||
|
||||
|
||||
struct {
|
||||
struct brw_winsys_buffer *state_bo;
|
||||
|
||||
struct brw_cc_unit_state cc;
|
||||
struct brw_winsys_reloc reloc[1];
|
||||
} cc;
|
||||
|
||||
struct {
|
||||
struct brw_query_object active_head;
|
||||
struct brw_winsys_buffer *bo;
|
||||
int index;
|
||||
GLboolean active;
|
||||
int stats_wm;
|
||||
} query;
|
||||
|
||||
struct {
|
||||
unsigned always_emit_state:1;
|
||||
unsigned always_flush_batch:1;
|
||||
unsigned force_swtnl:1;
|
||||
unsigned no_swtnl:1;
|
||||
} flags;
|
||||
|
||||
/* Used to give every program string a unique id
|
||||
*/
|
||||
GLuint program_id;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*======================================================================
|
||||
* brw_queryobj.c
|
||||
*/
|
||||
void brw_init_query(struct brw_context *brw);
|
||||
enum pipe_error brw_prepare_query_begin(struct brw_context *brw);
|
||||
void brw_emit_query_begin(struct brw_context *brw);
|
||||
void brw_emit_query_end(struct brw_context *brw);
|
||||
|
||||
/*======================================================================
|
||||
* brw_state_dump.c
|
||||
*/
|
||||
void brw_debug_batch(struct brw_context *intel);
|
||||
|
||||
|
||||
/*======================================================================
|
||||
* brw_pipe_*.c
|
||||
*/
|
||||
void brw_pipe_blend_init( struct brw_context *brw );
|
||||
void brw_pipe_depth_stencil_init( struct brw_context *brw );
|
||||
void brw_pipe_framebuffer_init( struct brw_context *brw );
|
||||
void brw_pipe_flush_init( struct brw_context *brw );
|
||||
void brw_pipe_misc_init( struct brw_context *brw );
|
||||
void brw_pipe_query_init( struct brw_context *brw );
|
||||
void brw_pipe_rast_init( struct brw_context *brw );
|
||||
void brw_pipe_sampler_init( struct brw_context *brw );
|
||||
void brw_pipe_shader_init( struct brw_context *brw );
|
||||
void brw_pipe_vertex_init( struct brw_context *brw );
|
||||
void brw_pipe_clear_init( struct brw_context *brw );
|
||||
|
||||
|
||||
void brw_pipe_blend_cleanup( struct brw_context *brw );
|
||||
void brw_pipe_depth_stencil_cleanup( struct brw_context *brw );
|
||||
void brw_pipe_framebuffer_cleanup( struct brw_context *brw );
|
||||
void brw_pipe_flush_cleanup( struct brw_context *brw );
|
||||
void brw_pipe_misc_cleanup( struct brw_context *brw );
|
||||
void brw_pipe_query_cleanup( struct brw_context *brw );
|
||||
void brw_pipe_rast_cleanup( struct brw_context *brw );
|
||||
void brw_pipe_sampler_cleanup( struct brw_context *brw );
|
||||
void brw_pipe_shader_cleanup( struct brw_context *brw );
|
||||
void brw_pipe_vertex_cleanup( struct brw_context *brw );
|
||||
void brw_pipe_clear_cleanup( struct brw_context *brw );
|
||||
|
||||
void brw_hw_cc_init( struct brw_context *brw );
|
||||
void brw_hw_cc_cleanup( struct brw_context *brw );
|
||||
|
||||
|
||||
|
||||
void brw_context_flush( struct brw_context *brw );
|
||||
|
||||
|
||||
/* brw_urb.c
|
||||
*/
|
||||
int brw_upload_urb_fence(struct brw_context *brw);
|
||||
|
||||
/* brw_curbe.c
|
||||
*/
|
||||
int brw_upload_cs_urb_state(struct brw_context *brw);
|
||||
|
||||
|
||||
/*======================================================================
|
||||
* Inline conversion functions. These are better-typed than the
|
||||
* macros used previously:
|
||||
*/
|
||||
static INLINE struct brw_context *
|
||||
brw_context( struct pipe_context *ctx )
|
||||
{
|
||||
return (struct brw_context *)ctx;
|
||||
}
|
||||
|
||||
|
||||
#define BRW_IS_965(brw) ((brw)->chipset.is_965)
|
||||
#define BRW_IS_IGDNG(brw) ((brw)->chipset.is_igdng)
|
||||
#define BRW_IS_G4X(brw) ((brw)->chipset.is_g4x)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_debug.h"
|
||||
#include "brw_screen.h"
|
||||
|
||||
|
||||
/**
|
||||
* Partition the CURBE between the various users of constant values:
|
||||
* Note that vertex and fragment shaders can now fetch constants out
|
||||
* of constant buffers. We no longer allocatea block of the GRF for
|
||||
* constants. That greatly reduces the demand for space in the CURBE.
|
||||
* Some of the comments within are dated...
|
||||
*/
|
||||
static int calculate_curbe_offsets( struct brw_context *brw )
|
||||
{
|
||||
/* CACHE_NEW_WM_PROG */
|
||||
const GLuint nr_fp_regs = brw->wm.prog_data->curb_read_length;
|
||||
|
||||
/* BRW_NEW_VERTEX_PROGRAM */
|
||||
const GLuint nr_vp_regs = brw->vs.prog_data->curb_read_length;
|
||||
GLuint nr_clip_regs = 0;
|
||||
GLuint total_regs;
|
||||
|
||||
/* PIPE_NEW_CLIP */
|
||||
if (brw->curr.ucp.nr) {
|
||||
GLuint nr_planes = 6 + brw->curr.ucp.nr;
|
||||
nr_clip_regs = (nr_planes * 4 + 15) / 16;
|
||||
}
|
||||
|
||||
|
||||
total_regs = nr_fp_regs + nr_vp_regs + nr_clip_regs;
|
||||
|
||||
/* When this is > 32, want to use a true constant buffer to hold
|
||||
* the extra constants.
|
||||
*/
|
||||
assert(total_regs <= 32);
|
||||
|
||||
/* Lazy resize:
|
||||
*/
|
||||
if (nr_fp_regs > brw->curbe.wm_size ||
|
||||
nr_vp_regs > brw->curbe.vs_size ||
|
||||
nr_clip_regs != brw->curbe.clip_size ||
|
||||
(total_regs < brw->curbe.total_size / 4 &&
|
||||
brw->curbe.total_size > 16)) {
|
||||
|
||||
GLuint reg = 0;
|
||||
|
||||
/* Calculate a new layout:
|
||||
*/
|
||||
reg = 0;
|
||||
brw->curbe.wm_start = reg;
|
||||
brw->curbe.wm_size = nr_fp_regs; reg += nr_fp_regs;
|
||||
brw->curbe.clip_start = reg;
|
||||
brw->curbe.clip_size = nr_clip_regs; reg += nr_clip_regs;
|
||||
brw->curbe.vs_start = reg;
|
||||
brw->curbe.vs_size = nr_vp_regs; reg += nr_vp_regs;
|
||||
brw->curbe.total_size = reg;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_CURBE)
|
||||
debug_printf("curbe wm %d+%d clip %d+%d vs %d+%d\n",
|
||||
brw->curbe.wm_start,
|
||||
brw->curbe.wm_size,
|
||||
brw->curbe.clip_start,
|
||||
brw->curbe.clip_size,
|
||||
brw->curbe.vs_start,
|
||||
brw->curbe.vs_size );
|
||||
|
||||
brw->state.dirty.brw |= BRW_NEW_CURBE_OFFSETS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const struct brw_tracked_state brw_curbe_offsets = {
|
||||
.dirty = {
|
||||
.mesa = PIPE_NEW_CLIP,
|
||||
.brw = BRW_NEW_VERTEX_PROGRAM,
|
||||
.cache = CACHE_NEW_WM_PROG
|
||||
},
|
||||
.prepare = calculate_curbe_offsets
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* Define the number of curbes within CS's urb allocation. Multiple
|
||||
* urb entries -> multiple curbes. These will be used by
|
||||
* fixed-function hardware in a double-buffering scheme to avoid a
|
||||
* pipeline stall each time the contents of the curbe is changed.
|
||||
*/
|
||||
int brw_upload_cs_urb_state(struct brw_context *brw)
|
||||
{
|
||||
struct brw_cs_urb_state cs_urb;
|
||||
memset(&cs_urb, 0, sizeof(cs_urb));
|
||||
|
||||
/* It appears that this is the state packet for the CS unit, ie. the
|
||||
* urb entries detailed here are housed in the CS range from the
|
||||
* URB_FENCE command.
|
||||
*/
|
||||
cs_urb.header.opcode = CMD_CS_URB_STATE;
|
||||
cs_urb.header.length = sizeof(cs_urb)/4 - 2;
|
||||
|
||||
/* BRW_NEW_URB_FENCE */
|
||||
cs_urb.bits0.nr_urb_entries = brw->urb.nr_cs_entries;
|
||||
cs_urb.bits0.urb_entry_size = brw->urb.csize - 1;
|
||||
|
||||
assert(brw->urb.nr_cs_entries);
|
||||
BRW_CACHED_BATCH_STRUCT(brw, &cs_urb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GLfloat fixed_plane[6][4] = {
|
||||
{ 0, 0, -1, 1 },
|
||||
{ 0, 0, 1, 1 },
|
||||
{ 0, -1, 0, 1 },
|
||||
{ 0, 1, 0, 1 },
|
||||
{-1, 0, 0, 1 },
|
||||
{ 1, 0, 0, 1 }
|
||||
};
|
||||
|
||||
/* Upload a new set of constants. Too much variability to go into the
|
||||
* cache mechanism, but maybe would benefit from a comparison against
|
||||
* the current uploaded set of constants.
|
||||
*/
|
||||
static enum pipe_error prepare_curbe_buffer(struct brw_context *brw)
|
||||
{
|
||||
struct pipe_screen *screen = brw->base.screen;
|
||||
const GLuint sz = brw->curbe.total_size;
|
||||
const GLuint bufsz = sz * 16 * sizeof(GLfloat);
|
||||
enum pipe_error ret;
|
||||
GLfloat *buf;
|
||||
GLuint i;
|
||||
|
||||
if (sz == 0) {
|
||||
if (brw->curbe.last_buf) {
|
||||
free(brw->curbe.last_buf);
|
||||
brw->curbe.last_buf = NULL;
|
||||
brw->curbe.last_bufsz = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = (GLfloat *) CALLOC(bufsz, 1);
|
||||
|
||||
/* fragment shader constants */
|
||||
if (brw->curbe.wm_size) {
|
||||
const struct brw_fragment_shader *fs = brw->curr.fragment_shader;
|
||||
GLuint offset = brw->curbe.wm_start * 16;
|
||||
GLuint nr_immediate, nr_const;
|
||||
|
||||
nr_immediate = fs->immediates.nr;
|
||||
if (nr_immediate) {
|
||||
memcpy(&buf[offset],
|
||||
fs->immediates.data,
|
||||
nr_immediate * 4 * sizeof(float));
|
||||
|
||||
offset += nr_immediate * 4;
|
||||
}
|
||||
|
||||
nr_const = fs->info.file_max[TGSI_FILE_CONSTANT] + 1;
|
||||
/* nr_const = brw->wm.prog_data->nr_params; */
|
||||
if (nr_const) {
|
||||
const GLfloat *value = screen->buffer_map( screen,
|
||||
brw->curr.fragment_constants,
|
||||
PIPE_BUFFER_USAGE_CPU_READ);
|
||||
|
||||
memcpy(&buf[offset], value,
|
||||
nr_const * 4 * sizeof(float));
|
||||
|
||||
screen->buffer_unmap( screen,
|
||||
brw->curr.fragment_constants );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The clipplanes are actually delivered to both CLIP and VS units.
|
||||
* VS uses them to calculate the outcode bitmasks.
|
||||
*/
|
||||
if (brw->curbe.clip_size) {
|
||||
GLuint offset = brw->curbe.clip_start * 16;
|
||||
GLuint j;
|
||||
|
||||
/* If any planes are going this way, send them all this way:
|
||||
*/
|
||||
for (i = 0; i < 6; i++) {
|
||||
buf[offset + i * 4 + 0] = fixed_plane[i][0];
|
||||
buf[offset + i * 4 + 1] = fixed_plane[i][1];
|
||||
buf[offset + i * 4 + 2] = fixed_plane[i][2];
|
||||
buf[offset + i * 4 + 3] = fixed_plane[i][3];
|
||||
}
|
||||
|
||||
/* Clip planes:
|
||||
*/
|
||||
assert(brw->curr.ucp.nr <= 6);
|
||||
for (j = 0; j < brw->curr.ucp.nr; j++) {
|
||||
buf[offset + i * 4 + 0] = brw->curr.ucp.ucp[j][0];
|
||||
buf[offset + i * 4 + 1] = brw->curr.ucp.ucp[j][1];
|
||||
buf[offset + i * 4 + 2] = brw->curr.ucp.ucp[j][2];
|
||||
buf[offset + i * 4 + 3] = brw->curr.ucp.ucp[j][3];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* vertex shader constants */
|
||||
if (brw->curbe.vs_size) {
|
||||
GLuint offset = brw->curbe.vs_start * 16;
|
||||
const struct brw_vertex_shader *vs = brw->curr.vertex_shader;
|
||||
GLuint nr_immediate, nr_const;
|
||||
|
||||
nr_immediate = vs->immediates.nr;
|
||||
if (nr_immediate) {
|
||||
memcpy(&buf[offset],
|
||||
vs->immediates.data,
|
||||
nr_immediate * 4 * sizeof(float));
|
||||
|
||||
offset += nr_immediate * 4;
|
||||
}
|
||||
|
||||
nr_const = vs->info.file_max[TGSI_FILE_CONSTANT] + 1;
|
||||
if (nr_const) {
|
||||
/* XXX: note that constant buffers are currently *already* in
|
||||
* buffer objects. If we want to keep on putting them into the
|
||||
* curbe, makes sense to treat constbuf's specially with malloc.
|
||||
*/
|
||||
const GLfloat *value = screen->buffer_map( screen,
|
||||
brw->curr.vertex_constants,
|
||||
PIPE_BUFFER_USAGE_CPU_READ);
|
||||
|
||||
/* XXX: what if user's constant buffer is too small?
|
||||
*/
|
||||
memcpy(&buf[offset], value, nr_const * 4 * sizeof(float));
|
||||
|
||||
screen->buffer_unmap( screen, brw->curr.vertex_constants );
|
||||
}
|
||||
}
|
||||
|
||||
if (BRW_DEBUG & DEBUG_CURBE) {
|
||||
for (i = 0; i < sz*16; i+=4)
|
||||
debug_printf("curbe %d.%d: %f %f %f %f\n", i/8, i&4,
|
||||
buf[i+0], buf[i+1], buf[i+2], buf[i+3]);
|
||||
|
||||
debug_printf("last_buf %p buf %p sz %d/%d cmp %d\n",
|
||||
(void *)brw->curbe.last_buf, (void *)buf,
|
||||
bufsz, brw->curbe.last_bufsz,
|
||||
brw->curbe.last_buf ? memcmp(buf, brw->curbe.last_buf, bufsz) : -1);
|
||||
}
|
||||
|
||||
if (brw->curbe.curbe_bo != NULL &&
|
||||
brw->curbe.last_buf &&
|
||||
bufsz == brw->curbe.last_bufsz &&
|
||||
memcmp(buf, brw->curbe.last_buf, bufsz) == 0) {
|
||||
/* constants have not changed */
|
||||
FREE(buf);
|
||||
}
|
||||
else {
|
||||
/* constants have changed */
|
||||
FREE(brw->curbe.last_buf);
|
||||
|
||||
brw->curbe.last_buf = buf;
|
||||
brw->curbe.last_bufsz = bufsz;
|
||||
|
||||
if (brw->curbe.curbe_bo != NULL &&
|
||||
(brw->curbe.need_new_bo ||
|
||||
brw->curbe.curbe_next_offset + bufsz > brw->curbe.curbe_bo->size))
|
||||
{
|
||||
bo_reference(&brw->curbe.curbe_bo, NULL);
|
||||
}
|
||||
|
||||
if (brw->curbe.curbe_bo == NULL) {
|
||||
/* Allocate a single page for CURBE entries for this
|
||||
* batchbuffer. They're generally around 64b. We will
|
||||
* discard the curbe buffer after the batch is flushed to
|
||||
* avoid synchronous updates.
|
||||
*/
|
||||
ret = brw->sws->bo_alloc(brw->sws,
|
||||
BRW_BUFFER_TYPE_CURBE,
|
||||
4096, 1 << 6,
|
||||
&brw->curbe.curbe_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
brw->curbe.curbe_next_offset = 0;
|
||||
}
|
||||
|
||||
brw->curbe.curbe_offset = brw->curbe.curbe_next_offset;
|
||||
brw->curbe.curbe_next_offset += bufsz;
|
||||
brw->curbe.curbe_next_offset = align(brw->curbe.curbe_next_offset, 64);
|
||||
|
||||
/* Copy data to the buffer:
|
||||
*/
|
||||
brw->sws->bo_subdata(brw->curbe.curbe_bo,
|
||||
BRW_DATA_CONSTANT_BUFFER,
|
||||
brw->curbe.curbe_offset,
|
||||
bufsz,
|
||||
buf,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
brw_add_validated_bo(brw, brw->curbe.curbe_bo);
|
||||
|
||||
/* Because this provokes an action (ie copy the constants into the
|
||||
* URB), it shouldn't be shortcircuited if identical to the
|
||||
* previous time - because eg. the urb destination may have
|
||||
* changed, or the urb contents different to last time.
|
||||
*
|
||||
* Note that the data referred to is actually copied internally,
|
||||
* not just used in place according to passed pointer.
|
||||
*
|
||||
* It appears that the CS unit takes care of using each available
|
||||
* URB entry (Const URB Entry == CURBE) in turn, and issuing
|
||||
* flushes as necessary when doublebuffering of CURBEs isn't
|
||||
* possible.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum pipe_error emit_curbe_buffer(struct brw_context *brw)
|
||||
{
|
||||
GLuint sz = brw->curbe.total_size;
|
||||
|
||||
BEGIN_BATCH(2, IGNORE_CLIPRECTS);
|
||||
if (sz == 0) {
|
||||
OUT_BATCH((CMD_CONST_BUFFER << 16) | (2 - 2));
|
||||
OUT_BATCH(0);
|
||||
} else {
|
||||
OUT_BATCH((CMD_CONST_BUFFER << 16) | (1 << 8) | (2 - 2));
|
||||
OUT_RELOC(brw->curbe.curbe_bo,
|
||||
BRW_USAGE_STATE,
|
||||
(sz - 1) + brw->curbe.curbe_offset);
|
||||
}
|
||||
ADVANCE_BATCH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_curbe_buffer = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_FRAGMENT_CONSTANTS |
|
||||
PIPE_NEW_VERTEX_CONSTANTS |
|
||||
PIPE_NEW_CLIP),
|
||||
.brw = (BRW_NEW_FRAGMENT_PROGRAM |
|
||||
BRW_NEW_VERTEX_PROGRAM |
|
||||
BRW_NEW_URB_FENCE | /* Implicit - hardware requires this, not used above */
|
||||
BRW_NEW_PSP | /* Implicit - hardware requires this, not used above */
|
||||
BRW_NEW_CURBE_OFFSETS |
|
||||
BRW_NEW_BATCH),
|
||||
.cache = (CACHE_NEW_WM_PROG)
|
||||
},
|
||||
.prepare = prepare_curbe_buffer,
|
||||
.emit = emit_curbe_buffer,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#ifndef BRW_DEBUG_H
|
||||
#define BRW_DEBUG_H
|
||||
|
||||
/* ================================================================
|
||||
* Debugging:
|
||||
*/
|
||||
|
||||
#define DEBUG_TEXTURE 0x1
|
||||
#define DEBUG_STATE 0x2
|
||||
#define DEBUG_IOCTL 0x4
|
||||
#define DEBUG_BLIT 0x8
|
||||
#define DEBUG_CURBE 0x10
|
||||
#define DEBUG_FALLBACKS 0x20
|
||||
#define DEBUG_VERBOSE 0x40
|
||||
#define DEBUG_BATCH 0x80
|
||||
#define DEBUG_PIXEL 0x100
|
||||
#define DEBUG_WINSYS 0x200
|
||||
#define DEBUG_MIN_URB 0x400
|
||||
#define DEBUG_DISASSEM 0x800
|
||||
#define DEBUG_unused3 0x1000
|
||||
#define DEBUG_SYNC 0x2000
|
||||
#define DEBUG_PRIMS 0x4000
|
||||
#define DEBUG_VERTS 0x8000
|
||||
#define DEBUG_unused4 0x10000
|
||||
#define DEBUG_DMA 0x20000
|
||||
#define DEBUG_SANITY 0x40000
|
||||
#define DEBUG_SLEEP 0x80000
|
||||
#define DEBUG_STATS 0x100000
|
||||
#define DEBUG_unused5 0x200000
|
||||
#define DEBUG_SINGLE_THREAD 0x400000
|
||||
#define DEBUG_WM 0x800000
|
||||
#define DEBUG_URB 0x1000000
|
||||
#define DEBUG_VS 0x2000000
|
||||
|
||||
#ifdef DEBUG
|
||||
extern int BRW_DEBUG;
|
||||
#else
|
||||
#define BRW_DEBUG 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,847 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BRW_DEFINES_H
|
||||
#define BRW_DEFINES_H
|
||||
|
||||
/* 3D state:
|
||||
*/
|
||||
#define _3DOP_3DSTATE_PIPELINED 0x0
|
||||
#define _3DOP_3DSTATE_NONPIPELINED 0x1
|
||||
#define _3DOP_3DCONTROL 0x2
|
||||
#define _3DOP_3DPRIMITIVE 0x3
|
||||
|
||||
#define _3DSTATE_PIPELINED_POINTERS 0x00
|
||||
#define _3DSTATE_BINDING_TABLE_POINTERS 0x01
|
||||
#define _3DSTATE_VERTEX_BUFFERS 0x08
|
||||
#define _3DSTATE_VERTEX_ELEMENTS 0x09
|
||||
#define _3DSTATE_INDEX_BUFFER 0x0A
|
||||
#define _3DSTATE_VF_STATISTICS 0x0B
|
||||
#define _3DSTATE_DRAWING_RECTANGLE 0x00
|
||||
#define _3DSTATE_CONSTANT_COLOR 0x01
|
||||
#define _3DSTATE_SAMPLER_PALETTE_LOAD 0x02
|
||||
#define _3DSTATE_CHROMA_KEY 0x04
|
||||
#define _3DSTATE_DEPTH_BUFFER 0x05
|
||||
#define _3DSTATE_POLY_STIPPLE_OFFSET 0x06
|
||||
#define _3DSTATE_POLY_STIPPLE_PATTERN 0x07
|
||||
#define _3DSTATE_LINE_STIPPLE 0x08
|
||||
#define _3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP 0x09
|
||||
#define _3DCONTROL 0x00
|
||||
|
||||
#define PIPE_CONTROL_NOWRITE 0x00
|
||||
#define PIPE_CONTROL_WRITEIMMEDIATE 0x01
|
||||
#define PIPE_CONTROL_WRITEDEPTH 0x02
|
||||
#define PIPE_CONTROL_WRITETIMESTAMP 0x03
|
||||
|
||||
#define PIPE_CONTROL_GTTWRITE_PROCESS_LOCAL 0x00
|
||||
#define PIPE_CONTROL_GTTWRITE_GLOBAL 0x01
|
||||
|
||||
#define _3DPRIM_POINTLIST 0x01
|
||||
#define _3DPRIM_LINELIST 0x02
|
||||
#define _3DPRIM_LINESTRIP 0x03
|
||||
#define _3DPRIM_TRILIST 0x04
|
||||
#define _3DPRIM_TRISTRIP 0x05
|
||||
#define _3DPRIM_TRIFAN 0x06
|
||||
#define _3DPRIM_QUADLIST 0x07
|
||||
#define _3DPRIM_QUADSTRIP 0x08
|
||||
#define _3DPRIM_LINELIST_ADJ 0x09
|
||||
#define _3DPRIM_LINESTRIP_ADJ 0x0A
|
||||
#define _3DPRIM_TRILIST_ADJ 0x0B
|
||||
#define _3DPRIM_TRISTRIP_ADJ 0x0C
|
||||
#define _3DPRIM_TRISTRIP_REVERSE 0x0D
|
||||
#define _3DPRIM_POLYGON 0x0E
|
||||
#define _3DPRIM_RECTLIST 0x0F
|
||||
#define _3DPRIM_LINELOOP 0x10
|
||||
#define _3DPRIM_POINTLIST_BF 0x11
|
||||
#define _3DPRIM_LINESTRIP_CONT 0x12
|
||||
#define _3DPRIM_LINESTRIP_BF 0x13
|
||||
#define _3DPRIM_LINESTRIP_CONT_BF 0x14
|
||||
#define _3DPRIM_TRIFAN_NOSTIPPLE 0x15
|
||||
|
||||
#define _3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL 0
|
||||
#define _3DPRIM_VERTEXBUFFER_ACCESS_RANDOM 1
|
||||
|
||||
#define BRW_ANISORATIO_2 0
|
||||
#define BRW_ANISORATIO_4 1
|
||||
#define BRW_ANISORATIO_6 2
|
||||
#define BRW_ANISORATIO_8 3
|
||||
#define BRW_ANISORATIO_10 4
|
||||
#define BRW_ANISORATIO_12 5
|
||||
#define BRW_ANISORATIO_14 6
|
||||
#define BRW_ANISORATIO_16 7
|
||||
|
||||
#define BRW_BLENDFACTOR_ONE 0x1
|
||||
#define BRW_BLENDFACTOR_SRC_COLOR 0x2
|
||||
#define BRW_BLENDFACTOR_SRC_ALPHA 0x3
|
||||
#define BRW_BLENDFACTOR_DST_ALPHA 0x4
|
||||
#define BRW_BLENDFACTOR_DST_COLOR 0x5
|
||||
#define BRW_BLENDFACTOR_SRC_ALPHA_SATURATE 0x6
|
||||
#define BRW_BLENDFACTOR_CONST_COLOR 0x7
|
||||
#define BRW_BLENDFACTOR_CONST_ALPHA 0x8
|
||||
#define BRW_BLENDFACTOR_SRC1_COLOR 0x9
|
||||
#define BRW_BLENDFACTOR_SRC1_ALPHA 0x0A
|
||||
#define BRW_BLENDFACTOR_ZERO 0x11
|
||||
#define BRW_BLENDFACTOR_INV_SRC_COLOR 0x12
|
||||
#define BRW_BLENDFACTOR_INV_SRC_ALPHA 0x13
|
||||
#define BRW_BLENDFACTOR_INV_DST_ALPHA 0x14
|
||||
#define BRW_BLENDFACTOR_INV_DST_COLOR 0x15
|
||||
#define BRW_BLENDFACTOR_INV_CONST_COLOR 0x17
|
||||
#define BRW_BLENDFACTOR_INV_CONST_ALPHA 0x18
|
||||
#define BRW_BLENDFACTOR_INV_SRC1_COLOR 0x19
|
||||
#define BRW_BLENDFACTOR_INV_SRC1_ALPHA 0x1A
|
||||
|
||||
#define BRW_BLENDFUNCTION_ADD 0
|
||||
#define BRW_BLENDFUNCTION_SUBTRACT 1
|
||||
#define BRW_BLENDFUNCTION_REVERSE_SUBTRACT 2
|
||||
#define BRW_BLENDFUNCTION_MIN 3
|
||||
#define BRW_BLENDFUNCTION_MAX 4
|
||||
|
||||
#define BRW_ALPHATEST_FORMAT_UNORM8 0
|
||||
#define BRW_ALPHATEST_FORMAT_FLOAT32 1
|
||||
|
||||
#define BRW_CHROMAKEY_KILL_ON_ANY_MATCH 0
|
||||
#define BRW_CHROMAKEY_REPLACE_BLACK 1
|
||||
|
||||
#define BRW_CLIP_API_OGL 0
|
||||
#define BRW_CLIP_API_DX 1
|
||||
|
||||
#define BRW_CLIPMODE_NORMAL 0
|
||||
#define BRW_CLIPMODE_CLIP_ALL 1
|
||||
#define BRW_CLIPMODE_CLIP_NON_REJECTED 2
|
||||
#define BRW_CLIPMODE_REJECT_ALL 3
|
||||
#define BRW_CLIPMODE_ACCEPT_ALL 4
|
||||
#define BRW_CLIPMODE_KERNEL_CLIP 5
|
||||
|
||||
#define BRW_CLIP_NDCSPACE 0
|
||||
#define BRW_CLIP_SCREENSPACE 1
|
||||
|
||||
#define BRW_COMPAREFUNCTION_ALWAYS 0
|
||||
#define BRW_COMPAREFUNCTION_NEVER 1
|
||||
#define BRW_COMPAREFUNCTION_LESS 2
|
||||
#define BRW_COMPAREFUNCTION_EQUAL 3
|
||||
#define BRW_COMPAREFUNCTION_LEQUAL 4
|
||||
#define BRW_COMPAREFUNCTION_GREATER 5
|
||||
#define BRW_COMPAREFUNCTION_NOTEQUAL 6
|
||||
#define BRW_COMPAREFUNCTION_GEQUAL 7
|
||||
|
||||
#define BRW_COVERAGE_PIXELS_HALF 0
|
||||
#define BRW_COVERAGE_PIXELS_1 1
|
||||
#define BRW_COVERAGE_PIXELS_2 2
|
||||
#define BRW_COVERAGE_PIXELS_4 3
|
||||
|
||||
#define BRW_CULLMODE_BOTH 0
|
||||
#define BRW_CULLMODE_NONE 1
|
||||
#define BRW_CULLMODE_FRONT 2
|
||||
#define BRW_CULLMODE_BACK 3
|
||||
|
||||
#define BRW_DEFAULTCOLOR_R8G8B8A8_UNORM 0
|
||||
#define BRW_DEFAULTCOLOR_R32G32B32A32_FLOAT 1
|
||||
|
||||
#define BRW_DEPTHFORMAT_D32_FLOAT_S8X24_UINT 0
|
||||
#define BRW_DEPTHFORMAT_D32_FLOAT 1
|
||||
#define BRW_DEPTHFORMAT_D24_UNORM_S8_UINT 2
|
||||
#define BRW_DEPTHFORMAT_D16_UNORM 5
|
||||
|
||||
#define BRW_FLOATING_POINT_IEEE_754 0
|
||||
#define BRW_FLOATING_POINT_NON_IEEE_754 1
|
||||
|
||||
#define BRW_FRONTWINDING_CW 0
|
||||
#define BRW_FRONTWINDING_CCW 1
|
||||
|
||||
#define BRW_SPRITE_POINT_ENABLE 16
|
||||
|
||||
#define BRW_INDEX_BYTE 0
|
||||
#define BRW_INDEX_WORD 1
|
||||
#define BRW_INDEX_DWORD 2
|
||||
|
||||
#define BRW_LOGICOPFUNCTION_CLEAR 0
|
||||
#define BRW_LOGICOPFUNCTION_NOR 1
|
||||
#define BRW_LOGICOPFUNCTION_AND_INVERTED 2
|
||||
#define BRW_LOGICOPFUNCTION_COPY_INVERTED 3
|
||||
#define BRW_LOGICOPFUNCTION_AND_REVERSE 4
|
||||
#define BRW_LOGICOPFUNCTION_INVERT 5
|
||||
#define BRW_LOGICOPFUNCTION_XOR 6
|
||||
#define BRW_LOGICOPFUNCTION_NAND 7
|
||||
#define BRW_LOGICOPFUNCTION_AND 8
|
||||
#define BRW_LOGICOPFUNCTION_EQUIV 9
|
||||
#define BRW_LOGICOPFUNCTION_NOOP 10
|
||||
#define BRW_LOGICOPFUNCTION_OR_INVERTED 11
|
||||
#define BRW_LOGICOPFUNCTION_COPY 12
|
||||
#define BRW_LOGICOPFUNCTION_OR_REVERSE 13
|
||||
#define BRW_LOGICOPFUNCTION_OR 14
|
||||
#define BRW_LOGICOPFUNCTION_SET 15
|
||||
|
||||
#define BRW_MAPFILTER_NEAREST 0x0
|
||||
#define BRW_MAPFILTER_LINEAR 0x1
|
||||
#define BRW_MAPFILTER_ANISOTROPIC 0x2
|
||||
|
||||
#define BRW_MIPFILTER_NONE 0
|
||||
#define BRW_MIPFILTER_NEAREST 1
|
||||
#define BRW_MIPFILTER_LINEAR 3
|
||||
|
||||
#define BRW_POLYGON_FRONT_FACING 0
|
||||
#define BRW_POLYGON_BACK_FACING 1
|
||||
|
||||
#define BRW_PREFILTER_ALWAYS 0x0
|
||||
#define BRW_PREFILTER_NEVER 0x1
|
||||
#define BRW_PREFILTER_LESS 0x2
|
||||
#define BRW_PREFILTER_EQUAL 0x3
|
||||
#define BRW_PREFILTER_LEQUAL 0x4
|
||||
#define BRW_PREFILTER_GREATER 0x5
|
||||
#define BRW_PREFILTER_NOTEQUAL 0x6
|
||||
#define BRW_PREFILTER_GEQUAL 0x7
|
||||
|
||||
#define BRW_PROVOKING_VERTEX_0 0
|
||||
#define BRW_PROVOKING_VERTEX_1 1
|
||||
#define BRW_PROVOKING_VERTEX_2 2
|
||||
|
||||
#define BRW_RASTRULE_UPPER_LEFT 0
|
||||
#define BRW_RASTRULE_UPPER_RIGHT 1
|
||||
/* These are listed as "Reserved, but not seen as useful"
|
||||
* in Intel documentation (page 212, "Point Rasterization Rule",
|
||||
* section 7.4 "SF Pipeline State Summary", of document
|
||||
* "Intel® 965 Express Chipset Family and Intel® G35 Express
|
||||
* Chipset Graphics Controller Programmer's Reference Manual,
|
||||
* Volume 2: 3D/Media", Revision 1.0b as of January 2008,
|
||||
* available at
|
||||
* http://intellinuxgraphics.org/documentation.html
|
||||
* at the time of this writing).
|
||||
*
|
||||
* These appear to be supported on at least some
|
||||
* i965-family devices, and the BRW_RASTRULE_LOWER_RIGHT
|
||||
* is useful when using OpenGL to render to a FBO
|
||||
* (which has the pixel coordinate Y orientation inverted
|
||||
* with respect to the normal OpenGL pixel coordinate system).
|
||||
*/
|
||||
#define BRW_RASTRULE_LOWER_LEFT 2
|
||||
#define BRW_RASTRULE_LOWER_RIGHT 3
|
||||
|
||||
#define BRW_RENDERTARGET_CLAMPRANGE_UNORM 0
|
||||
#define BRW_RENDERTARGET_CLAMPRANGE_SNORM 1
|
||||
#define BRW_RENDERTARGET_CLAMPRANGE_FORMAT 2
|
||||
|
||||
#define BRW_STENCILOP_KEEP 0
|
||||
#define BRW_STENCILOP_ZERO 1
|
||||
#define BRW_STENCILOP_REPLACE 2
|
||||
#define BRW_STENCILOP_INCRSAT 3
|
||||
#define BRW_STENCILOP_DECRSAT 4
|
||||
#define BRW_STENCILOP_INCR 5
|
||||
#define BRW_STENCILOP_DECR 6
|
||||
#define BRW_STENCILOP_INVERT 7
|
||||
|
||||
#define BRW_SURFACE_MIPMAPLAYOUT_BELOW 0
|
||||
#define BRW_SURFACE_MIPMAPLAYOUT_RIGHT 1
|
||||
|
||||
#define BRW_SURFACEFORMAT_R32G32B32A32_FLOAT 0x000
|
||||
#define BRW_SURFACEFORMAT_R32G32B32A32_SINT 0x001
|
||||
#define BRW_SURFACEFORMAT_R32G32B32A32_UINT 0x002
|
||||
#define BRW_SURFACEFORMAT_R32G32B32A32_UNORM 0x003
|
||||
#define BRW_SURFACEFORMAT_R32G32B32A32_SNORM 0x004
|
||||
#define BRW_SURFACEFORMAT_R64G64_FLOAT 0x005
|
||||
#define BRW_SURFACEFORMAT_R32G32B32X32_FLOAT 0x006
|
||||
#define BRW_SURFACEFORMAT_R32G32B32A32_SSCALED 0x007
|
||||
#define BRW_SURFACEFORMAT_R32G32B32A32_USCALED 0x008
|
||||
#define BRW_SURFACEFORMAT_R32G32B32_FLOAT 0x040
|
||||
#define BRW_SURFACEFORMAT_R32G32B32_SINT 0x041
|
||||
#define BRW_SURFACEFORMAT_R32G32B32_UINT 0x042
|
||||
#define BRW_SURFACEFORMAT_R32G32B32_UNORM 0x043
|
||||
#define BRW_SURFACEFORMAT_R32G32B32_SNORM 0x044
|
||||
#define BRW_SURFACEFORMAT_R32G32B32_SSCALED 0x045
|
||||
#define BRW_SURFACEFORMAT_R32G32B32_USCALED 0x046
|
||||
#define BRW_SURFACEFORMAT_R16G16B16A16_UNORM 0x080
|
||||
#define BRW_SURFACEFORMAT_R16G16B16A16_SNORM 0x081
|
||||
#define BRW_SURFACEFORMAT_R16G16B16A16_SINT 0x082
|
||||
#define BRW_SURFACEFORMAT_R16G16B16A16_UINT 0x083
|
||||
#define BRW_SURFACEFORMAT_R16G16B16A16_FLOAT 0x084
|
||||
#define BRW_SURFACEFORMAT_R32G32_FLOAT 0x085
|
||||
#define BRW_SURFACEFORMAT_R32G32_SINT 0x086
|
||||
#define BRW_SURFACEFORMAT_R32G32_UINT 0x087
|
||||
#define BRW_SURFACEFORMAT_R32_FLOAT_X8X24_TYPELESS 0x088
|
||||
#define BRW_SURFACEFORMAT_X32_TYPELESS_G8X24_UINT 0x089
|
||||
#define BRW_SURFACEFORMAT_L32A32_FLOAT 0x08A
|
||||
#define BRW_SURFACEFORMAT_R32G32_UNORM 0x08B
|
||||
#define BRW_SURFACEFORMAT_R32G32_SNORM 0x08C
|
||||
#define BRW_SURFACEFORMAT_R64_FLOAT 0x08D
|
||||
#define BRW_SURFACEFORMAT_R16G16B16X16_UNORM 0x08E
|
||||
#define BRW_SURFACEFORMAT_R16G16B16X16_FLOAT 0x08F
|
||||
#define BRW_SURFACEFORMAT_A32X32_FLOAT 0x090
|
||||
#define BRW_SURFACEFORMAT_L32X32_FLOAT 0x091
|
||||
#define BRW_SURFACEFORMAT_I32X32_FLOAT 0x092
|
||||
#define BRW_SURFACEFORMAT_R16G16B16A16_SSCALED 0x093
|
||||
#define BRW_SURFACEFORMAT_R16G16B16A16_USCALED 0x094
|
||||
#define BRW_SURFACEFORMAT_R32G32_SSCALED 0x095
|
||||
#define BRW_SURFACEFORMAT_R32G32_USCALED 0x096
|
||||
#define BRW_SURFACEFORMAT_B8G8R8A8_UNORM 0x0C0
|
||||
#define BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB 0x0C1
|
||||
#define BRW_SURFACEFORMAT_R10G10B10A2_UNORM 0x0C2
|
||||
#define BRW_SURFACEFORMAT_R10G10B10A2_UNORM_SRGB 0x0C3
|
||||
#define BRW_SURFACEFORMAT_R10G10B10A2_UINT 0x0C4
|
||||
#define BRW_SURFACEFORMAT_R10G10B10_SNORM_A2_UNORM 0x0C5
|
||||
#define BRW_SURFACEFORMAT_R8G8B8A8_UNORM 0x0C7
|
||||
#define BRW_SURFACEFORMAT_R8G8B8A8_UNORM_SRGB 0x0C8
|
||||
#define BRW_SURFACEFORMAT_R8G8B8A8_SNORM 0x0C9
|
||||
#define BRW_SURFACEFORMAT_R8G8B8A8_SINT 0x0CA
|
||||
#define BRW_SURFACEFORMAT_R8G8B8A8_UINT 0x0CB
|
||||
#define BRW_SURFACEFORMAT_R16G16_UNORM 0x0CC
|
||||
#define BRW_SURFACEFORMAT_R16G16_SNORM 0x0CD
|
||||
#define BRW_SURFACEFORMAT_R16G16_SINT 0x0CE
|
||||
#define BRW_SURFACEFORMAT_R16G16_UINT 0x0CF
|
||||
#define BRW_SURFACEFORMAT_R16G16_FLOAT 0x0D0
|
||||
#define BRW_SURFACEFORMAT_B10G10R10A2_UNORM 0x0D1
|
||||
#define BRW_SURFACEFORMAT_B10G10R10A2_UNORM_SRGB 0x0D2
|
||||
#define BRW_SURFACEFORMAT_R11G11B10_FLOAT 0x0D3
|
||||
#define BRW_SURFACEFORMAT_R32_SINT 0x0D6
|
||||
#define BRW_SURFACEFORMAT_R32_UINT 0x0D7
|
||||
#define BRW_SURFACEFORMAT_R32_FLOAT 0x0D8
|
||||
#define BRW_SURFACEFORMAT_R24_UNORM_X8_TYPELESS 0x0D9
|
||||
#define BRW_SURFACEFORMAT_X24_TYPELESS_G8_UINT 0x0DA
|
||||
#define BRW_SURFACEFORMAT_L16A16_UNORM 0x0DF
|
||||
#define BRW_SURFACEFORMAT_I24X8_UNORM 0x0E0
|
||||
#define BRW_SURFACEFORMAT_L24X8_UNORM 0x0E1
|
||||
#define BRW_SURFACEFORMAT_A24X8_UNORM 0x0E2
|
||||
#define BRW_SURFACEFORMAT_I32_FLOAT 0x0E3
|
||||
#define BRW_SURFACEFORMAT_L32_FLOAT 0x0E4
|
||||
#define BRW_SURFACEFORMAT_A32_FLOAT 0x0E5
|
||||
#define BRW_SURFACEFORMAT_B8G8R8X8_UNORM 0x0E9
|
||||
#define BRW_SURFACEFORMAT_B8G8R8X8_UNORM_SRGB 0x0EA
|
||||
#define BRW_SURFACEFORMAT_R8G8B8X8_UNORM 0x0EB
|
||||
#define BRW_SURFACEFORMAT_R8G8B8X8_UNORM_SRGB 0x0EC
|
||||
#define BRW_SURFACEFORMAT_R9G9B9E5_SHAREDEXP 0x0ED
|
||||
#define BRW_SURFACEFORMAT_B10G10R10X2_UNORM 0x0EE
|
||||
#define BRW_SURFACEFORMAT_L16A16_FLOAT 0x0F0
|
||||
#define BRW_SURFACEFORMAT_R32_UNORM 0x0F1
|
||||
#define BRW_SURFACEFORMAT_R32_SNORM 0x0F2
|
||||
#define BRW_SURFACEFORMAT_R10G10B10X2_USCALED 0x0F3
|
||||
#define BRW_SURFACEFORMAT_R8G8B8A8_SSCALED 0x0F4
|
||||
#define BRW_SURFACEFORMAT_R8G8B8A8_USCALED 0x0F5
|
||||
#define BRW_SURFACEFORMAT_R16G16_SSCALED 0x0F6
|
||||
#define BRW_SURFACEFORMAT_R16G16_USCALED 0x0F7
|
||||
#define BRW_SURFACEFORMAT_R32_SSCALED 0x0F8
|
||||
#define BRW_SURFACEFORMAT_R32_USCALED 0x0F9
|
||||
#define BRW_SURFACEFORMAT_B5G6R5_UNORM 0x100
|
||||
#define BRW_SURFACEFORMAT_B5G6R5_UNORM_SRGB 0x101
|
||||
#define BRW_SURFACEFORMAT_B5G5R5A1_UNORM 0x102
|
||||
#define BRW_SURFACEFORMAT_B5G5R5A1_UNORM_SRGB 0x103
|
||||
#define BRW_SURFACEFORMAT_B4G4R4A4_UNORM 0x104
|
||||
#define BRW_SURFACEFORMAT_B4G4R4A4_UNORM_SRGB 0x105
|
||||
#define BRW_SURFACEFORMAT_R8G8_UNORM 0x106
|
||||
#define BRW_SURFACEFORMAT_R8G8_SNORM 0x107
|
||||
#define BRW_SURFACEFORMAT_R8G8_SINT 0x108
|
||||
#define BRW_SURFACEFORMAT_R8G8_UINT 0x109
|
||||
#define BRW_SURFACEFORMAT_R16_UNORM 0x10A
|
||||
#define BRW_SURFACEFORMAT_R16_SNORM 0x10B
|
||||
#define BRW_SURFACEFORMAT_R16_SINT 0x10C
|
||||
#define BRW_SURFACEFORMAT_R16_UINT 0x10D
|
||||
#define BRW_SURFACEFORMAT_R16_FLOAT 0x10E
|
||||
#define BRW_SURFACEFORMAT_I16_UNORM 0x111
|
||||
#define BRW_SURFACEFORMAT_L16_UNORM 0x112
|
||||
#define BRW_SURFACEFORMAT_A16_UNORM 0x113
|
||||
#define BRW_SURFACEFORMAT_L8A8_UNORM 0x114
|
||||
#define BRW_SURFACEFORMAT_I16_FLOAT 0x115
|
||||
#define BRW_SURFACEFORMAT_L16_FLOAT 0x116
|
||||
#define BRW_SURFACEFORMAT_A16_FLOAT 0x117
|
||||
#define BRW_SURFACEFORMAT_L8A8_UNORM_SRGB 0x118
|
||||
#define BRW_SURFACEFORMAT_R5G5_SNORM_B6_UNORM 0x119
|
||||
#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM 0x11A
|
||||
#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM_SRGB 0x11B
|
||||
#define BRW_SURFACEFORMAT_R8G8_SSCALED 0x11C
|
||||
#define BRW_SURFACEFORMAT_R8G8_USCALED 0x11D
|
||||
#define BRW_SURFACEFORMAT_R16_SSCALED 0x11E
|
||||
#define BRW_SURFACEFORMAT_R16_USCALED 0x11F
|
||||
#define BRW_SURFACEFORMAT_R8_UNORM 0x140
|
||||
#define BRW_SURFACEFORMAT_R8_SNORM 0x141
|
||||
#define BRW_SURFACEFORMAT_R8_SINT 0x142
|
||||
#define BRW_SURFACEFORMAT_R8_UINT 0x143
|
||||
#define BRW_SURFACEFORMAT_A8_UNORM 0x144
|
||||
#define BRW_SURFACEFORMAT_I8_UNORM 0x145
|
||||
#define BRW_SURFACEFORMAT_L8_UNORM 0x146
|
||||
#define BRW_SURFACEFORMAT_P4A4_UNORM 0x147
|
||||
#define BRW_SURFACEFORMAT_A4P4_UNORM 0x148
|
||||
#define BRW_SURFACEFORMAT_R8_SSCALED 0x149
|
||||
#define BRW_SURFACEFORMAT_R8_USCALED 0x14A
|
||||
#define BRW_SURFACEFORMAT_L8_UNORM_SRGB 0x14C
|
||||
#define BRW_SURFACEFORMAT_R1_UINT 0x181
|
||||
#define BRW_SURFACEFORMAT_YCRCB_NORMAL 0x182
|
||||
#define BRW_SURFACEFORMAT_YCRCB_SWAPUVY 0x183
|
||||
#define BRW_SURFACEFORMAT_BC1_UNORM 0x186
|
||||
#define BRW_SURFACEFORMAT_BC2_UNORM 0x187
|
||||
#define BRW_SURFACEFORMAT_BC3_UNORM 0x188
|
||||
#define BRW_SURFACEFORMAT_BC4_UNORM 0x189
|
||||
#define BRW_SURFACEFORMAT_BC5_UNORM 0x18A
|
||||
#define BRW_SURFACEFORMAT_BC1_UNORM_SRGB 0x18B
|
||||
#define BRW_SURFACEFORMAT_BC2_UNORM_SRGB 0x18C
|
||||
#define BRW_SURFACEFORMAT_BC3_UNORM_SRGB 0x18D
|
||||
#define BRW_SURFACEFORMAT_MONO8 0x18E
|
||||
#define BRW_SURFACEFORMAT_YCRCB_SWAPUV 0x18F
|
||||
#define BRW_SURFACEFORMAT_YCRCB_SWAPY 0x190
|
||||
#define BRW_SURFACEFORMAT_DXT1_RGB 0x191
|
||||
#define BRW_SURFACEFORMAT_FXT1 0x192
|
||||
#define BRW_SURFACEFORMAT_R8G8B8_UNORM 0x193
|
||||
#define BRW_SURFACEFORMAT_R8G8B8_SNORM 0x194
|
||||
#define BRW_SURFACEFORMAT_R8G8B8_SSCALED 0x195
|
||||
#define BRW_SURFACEFORMAT_R8G8B8_USCALED 0x196
|
||||
#define BRW_SURFACEFORMAT_R64G64B64A64_FLOAT 0x197
|
||||
#define BRW_SURFACEFORMAT_R64G64B64_FLOAT 0x198
|
||||
#define BRW_SURFACEFORMAT_BC4_SNORM 0x199
|
||||
#define BRW_SURFACEFORMAT_BC5_SNORM 0x19A
|
||||
#define BRW_SURFACEFORMAT_R16G16B16_UNORM 0x19C
|
||||
#define BRW_SURFACEFORMAT_R16G16B16_SNORM 0x19D
|
||||
#define BRW_SURFACEFORMAT_R16G16B16_SSCALED 0x19E
|
||||
#define BRW_SURFACEFORMAT_R16G16B16_USCALED 0x19F
|
||||
#define BRW_SURFACEFORMAT_INVALID 0xFFF
|
||||
|
||||
#define BRW_SURFACERETURNFORMAT_FLOAT32 0
|
||||
#define BRW_SURFACERETURNFORMAT_S1 1
|
||||
|
||||
#define BRW_SURFACE_1D 0
|
||||
#define BRW_SURFACE_2D 1
|
||||
#define BRW_SURFACE_3D 2
|
||||
#define BRW_SURFACE_CUBE 3
|
||||
#define BRW_SURFACE_BUFFER 4
|
||||
#define BRW_SURFACE_NULL 7
|
||||
|
||||
#define BRW_TEXCOORDMODE_WRAP 0
|
||||
#define BRW_TEXCOORDMODE_MIRROR 1
|
||||
#define BRW_TEXCOORDMODE_CLAMP 2
|
||||
#define BRW_TEXCOORDMODE_CUBE 3
|
||||
#define BRW_TEXCOORDMODE_CLAMP_BORDER 4
|
||||
#define BRW_TEXCOORDMODE_MIRROR_ONCE 5
|
||||
|
||||
#define BRW_THREAD_PRIORITY_NORMAL 0
|
||||
#define BRW_THREAD_PRIORITY_HIGH 1
|
||||
|
||||
#define BRW_TILEWALK_XMAJOR 0
|
||||
#define BRW_TILEWALK_YMAJOR 1
|
||||
|
||||
#define BRW_VERTEX_SUBPIXEL_PRECISION_8BITS 0
|
||||
#define BRW_VERTEX_SUBPIXEL_PRECISION_4BITS 1
|
||||
|
||||
/* Execution Unit (EU) defines
|
||||
*/
|
||||
|
||||
#define BRW_ALIGN_1 0
|
||||
#define BRW_ALIGN_16 1
|
||||
|
||||
#define BRW_ADDRESS_DIRECT 0
|
||||
#define BRW_ADDRESS_REGISTER_INDIRECT_REGISTER 1
|
||||
|
||||
#define BRW_CHANNEL_X 0
|
||||
#define BRW_CHANNEL_Y 1
|
||||
#define BRW_CHANNEL_Z 2
|
||||
#define BRW_CHANNEL_W 3
|
||||
|
||||
#define BRW_COMPRESSION_NONE 0
|
||||
#define BRW_COMPRESSION_2NDHALF 1
|
||||
#define BRW_COMPRESSION_COMPRESSED 2
|
||||
|
||||
#define BRW_CONDITIONAL_NONE 0
|
||||
#define BRW_CONDITIONAL_Z 1
|
||||
#define BRW_CONDITIONAL_NZ 2
|
||||
#define BRW_CONDITIONAL_EQ 1 /* Z */
|
||||
#define BRW_CONDITIONAL_NEQ 2 /* NZ */
|
||||
#define BRW_CONDITIONAL_G 3
|
||||
#define BRW_CONDITIONAL_GE 4
|
||||
#define BRW_CONDITIONAL_L 5
|
||||
#define BRW_CONDITIONAL_LE 6
|
||||
#define BRW_CONDITIONAL_R 7
|
||||
#define BRW_CONDITIONAL_O 8
|
||||
#define BRW_CONDITIONAL_U 9
|
||||
|
||||
#define BRW_DEBUG_NONE 0
|
||||
#define BRW_DEBUG_BREAKPOINT 1
|
||||
|
||||
#define BRW_DEPENDENCY_NORMAL 0
|
||||
#define BRW_DEPENDENCY_NOTCLEARED 1
|
||||
#define BRW_DEPENDENCY_NOTCHECKED 2
|
||||
#define BRW_DEPENDENCY_DISABLE 3
|
||||
|
||||
#define BRW_EXECUTE_1 0
|
||||
#define BRW_EXECUTE_2 1
|
||||
#define BRW_EXECUTE_4 2
|
||||
#define BRW_EXECUTE_8 3
|
||||
#define BRW_EXECUTE_16 4
|
||||
#define BRW_EXECUTE_32 5
|
||||
|
||||
#define BRW_HORIZONTAL_STRIDE_0 0
|
||||
#define BRW_HORIZONTAL_STRIDE_1 1
|
||||
#define BRW_HORIZONTAL_STRIDE_2 2
|
||||
#define BRW_HORIZONTAL_STRIDE_4 3
|
||||
|
||||
#define BRW_INSTRUCTION_NORMAL 0
|
||||
#define BRW_INSTRUCTION_SATURATE 1
|
||||
|
||||
#define BRW_MASK_ENABLE 0
|
||||
#define BRW_MASK_DISABLE 1
|
||||
|
||||
#define BRW_OPCODE_MOV 1
|
||||
#define BRW_OPCODE_SEL 2
|
||||
#define BRW_OPCODE_NOT 4
|
||||
#define BRW_OPCODE_AND 5
|
||||
#define BRW_OPCODE_OR 6
|
||||
#define BRW_OPCODE_XOR 7
|
||||
#define BRW_OPCODE_SHR 8
|
||||
#define BRW_OPCODE_SHL 9
|
||||
#define BRW_OPCODE_RSR 10
|
||||
#define BRW_OPCODE_RSL 11
|
||||
#define BRW_OPCODE_ASR 12
|
||||
#define BRW_OPCODE_CMP 16
|
||||
#define BRW_OPCODE_CMPN 17
|
||||
#define BRW_OPCODE_JMPI 32
|
||||
#define BRW_OPCODE_IF 34
|
||||
#define BRW_OPCODE_IFF 35
|
||||
#define BRW_OPCODE_ELSE 36
|
||||
#define BRW_OPCODE_ENDIF 37
|
||||
#define BRW_OPCODE_DO 38
|
||||
#define BRW_OPCODE_WHILE 39
|
||||
#define BRW_OPCODE_BREAK 40
|
||||
#define BRW_OPCODE_CONTINUE 41
|
||||
#define BRW_OPCODE_HALT 42
|
||||
#define BRW_OPCODE_MSAVE 44
|
||||
#define BRW_OPCODE_MRESTORE 45
|
||||
#define BRW_OPCODE_PUSH 46
|
||||
#define BRW_OPCODE_POP 47
|
||||
#define BRW_OPCODE_WAIT 48
|
||||
#define BRW_OPCODE_SEND 49
|
||||
#define BRW_OPCODE_ADD 64
|
||||
#define BRW_OPCODE_MUL 65
|
||||
#define BRW_OPCODE_AVG 66
|
||||
#define BRW_OPCODE_FRC 67
|
||||
#define BRW_OPCODE_RNDU 68
|
||||
#define BRW_OPCODE_RNDD 69
|
||||
#define BRW_OPCODE_RNDE 70
|
||||
#define BRW_OPCODE_RNDZ 71
|
||||
#define BRW_OPCODE_MAC 72
|
||||
#define BRW_OPCODE_MACH 73
|
||||
#define BRW_OPCODE_LZD 74
|
||||
#define BRW_OPCODE_SAD2 80
|
||||
#define BRW_OPCODE_SADA2 81
|
||||
#define BRW_OPCODE_DP4 84
|
||||
#define BRW_OPCODE_DPH 85
|
||||
#define BRW_OPCODE_DP3 86
|
||||
#define BRW_OPCODE_DP2 87
|
||||
#define BRW_OPCODE_DPA2 88
|
||||
#define BRW_OPCODE_LINE 89
|
||||
#define BRW_OPCODE_NOP 126
|
||||
|
||||
#define BRW_PREDICATE_NONE 0
|
||||
#define BRW_PREDICATE_NORMAL 1
|
||||
#define BRW_PREDICATE_ALIGN1_ANYV 2
|
||||
#define BRW_PREDICATE_ALIGN1_ALLV 3
|
||||
#define BRW_PREDICATE_ALIGN1_ANY2H 4
|
||||
#define BRW_PREDICATE_ALIGN1_ALL2H 5
|
||||
#define BRW_PREDICATE_ALIGN1_ANY4H 6
|
||||
#define BRW_PREDICATE_ALIGN1_ALL4H 7
|
||||
#define BRW_PREDICATE_ALIGN1_ANY8H 8
|
||||
#define BRW_PREDICATE_ALIGN1_ALL8H 9
|
||||
#define BRW_PREDICATE_ALIGN1_ANY16H 10
|
||||
#define BRW_PREDICATE_ALIGN1_ALL16H 11
|
||||
#define BRW_PREDICATE_ALIGN16_REPLICATE_X 2
|
||||
#define BRW_PREDICATE_ALIGN16_REPLICATE_Y 3
|
||||
#define BRW_PREDICATE_ALIGN16_REPLICATE_Z 4
|
||||
#define BRW_PREDICATE_ALIGN16_REPLICATE_W 5
|
||||
#define BRW_PREDICATE_ALIGN16_ANY4H 6
|
||||
#define BRW_PREDICATE_ALIGN16_ALL4H 7
|
||||
|
||||
#define BRW_ARCHITECTURE_REGISTER_FILE 0
|
||||
#define BRW_GENERAL_REGISTER_FILE 1
|
||||
#define BRW_MESSAGE_REGISTER_FILE 2
|
||||
#define BRW_IMMEDIATE_VALUE 3
|
||||
|
||||
#define BRW_REGISTER_TYPE_UD 0
|
||||
#define BRW_REGISTER_TYPE_D 1
|
||||
#define BRW_REGISTER_TYPE_UW 2
|
||||
#define BRW_REGISTER_TYPE_W 3
|
||||
#define BRW_REGISTER_TYPE_UB 4
|
||||
#define BRW_REGISTER_TYPE_B 5
|
||||
#define BRW_REGISTER_TYPE_VF 5 /* packed float vector, immediates only? */
|
||||
#define BRW_REGISTER_TYPE_HF 6
|
||||
#define BRW_REGISTER_TYPE_V 6 /* packed int vector, immediates only, uword dest only */
|
||||
#define BRW_REGISTER_TYPE_F 7
|
||||
|
||||
#define BRW_ARF_NULL 0x00
|
||||
#define BRW_ARF_ADDRESS 0x10
|
||||
#define BRW_ARF_ACCUMULATOR 0x20
|
||||
#define BRW_ARF_FLAG 0x30
|
||||
#define BRW_ARF_MASK 0x40
|
||||
#define BRW_ARF_MASK_STACK 0x50
|
||||
#define BRW_ARF_MASK_STACK_DEPTH 0x60
|
||||
#define BRW_ARF_STATE 0x70
|
||||
#define BRW_ARF_CONTROL 0x80
|
||||
#define BRW_ARF_NOTIFICATION_COUNT 0x90
|
||||
#define BRW_ARF_IP 0xA0
|
||||
|
||||
#define BRW_AMASK 0
|
||||
#define BRW_IMASK 1
|
||||
#define BRW_LMASK 2
|
||||
#define BRW_CMASK 3
|
||||
|
||||
|
||||
|
||||
#define BRW_THREAD_NORMAL 0
|
||||
#define BRW_THREAD_ATOMIC 1
|
||||
#define BRW_THREAD_SWITCH 2
|
||||
|
||||
#define BRW_VERTICAL_STRIDE_0 0
|
||||
#define BRW_VERTICAL_STRIDE_1 1
|
||||
#define BRW_VERTICAL_STRIDE_2 2
|
||||
#define BRW_VERTICAL_STRIDE_4 3
|
||||
#define BRW_VERTICAL_STRIDE_8 4
|
||||
#define BRW_VERTICAL_STRIDE_16 5
|
||||
#define BRW_VERTICAL_STRIDE_32 6
|
||||
#define BRW_VERTICAL_STRIDE_64 7
|
||||
#define BRW_VERTICAL_STRIDE_128 8
|
||||
#define BRW_VERTICAL_STRIDE_256 9
|
||||
#define BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL 0xF
|
||||
|
||||
#define BRW_WIDTH_1 0
|
||||
#define BRW_WIDTH_2 1
|
||||
#define BRW_WIDTH_4 2
|
||||
#define BRW_WIDTH_8 3
|
||||
#define BRW_WIDTH_16 4
|
||||
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_1K 0
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_2K 1
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_4K 2
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_8K 3
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_16K 4
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_32K 5
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_64K 6
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_128K 7
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_256K 8
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_512K 9
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_1M 10
|
||||
#define BRW_STATELESS_BUFFER_BOUNDARY_2M 11
|
||||
|
||||
#define BRW_POLYGON_FACING_FRONT 0
|
||||
#define BRW_POLYGON_FACING_BACK 1
|
||||
|
||||
#define BRW_MESSAGE_TARGET_NULL 0
|
||||
#define BRW_MESSAGE_TARGET_MATH 1
|
||||
#define BRW_MESSAGE_TARGET_SAMPLER 2
|
||||
#define BRW_MESSAGE_TARGET_GATEWAY 3
|
||||
#define BRW_MESSAGE_TARGET_DATAPORT_READ 4
|
||||
#define BRW_MESSAGE_TARGET_DATAPORT_WRITE 5
|
||||
#define BRW_MESSAGE_TARGET_URB 6
|
||||
#define BRW_MESSAGE_TARGET_THREAD_SPAWNER 7
|
||||
|
||||
#define BRW_SAMPLER_RETURN_FORMAT_FLOAT32 0
|
||||
#define BRW_SAMPLER_RETURN_FORMAT_UINT32 2
|
||||
#define BRW_SAMPLER_RETURN_FORMAT_SINT32 3
|
||||
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE 0
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE 0
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS 0
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD8_KILLPIX 1
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD 1
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD 1
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_GRADIENTS 2
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_GRADIENTS 2
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_COMPARE 0
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE 2
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD4X2_RESINFO 2
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD8_RESINFO 2
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD16_RESINFO 2
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD4X2_LD 3
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD8_LD 3
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD16_LD 3
|
||||
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_IGDNG 0
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_IGDNG 0
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_IGDNG 0
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_BIAS_IGDNG 1
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_BIAS_IGDNG 1
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS_IGDNG 1
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_LOD_IGDNG 2
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD_IGDNG 2
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD_IGDNG 2
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_COMPARE_IGDNG 3
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_COMPARE_IGDNG 3
|
||||
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE_IGDNG 3
|
||||
|
||||
/* for IGDNG only */
|
||||
#define BRW_SAMPLER_SIMD_MODE_SIMD4X2 0
|
||||
#define BRW_SAMPLER_SIMD_MODE_SIMD8 1
|
||||
#define BRW_SAMPLER_SIMD_MODE_SIMD16 2
|
||||
#define BRW_SAMPLER_SIMD_MODE_SIMD32_64 3
|
||||
|
||||
#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDLOW 0
|
||||
#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDHIGH 1
|
||||
#define BRW_DATAPORT_OWORD_BLOCK_2_OWORDS 2
|
||||
#define BRW_DATAPORT_OWORD_BLOCK_4_OWORDS 3
|
||||
#define BRW_DATAPORT_OWORD_BLOCK_8_OWORDS 4
|
||||
|
||||
#define BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD 0
|
||||
#define BRW_DATAPORT_OWORD_DUAL_BLOCK_4OWORDS 2
|
||||
|
||||
#define BRW_DATAPORT_DWORD_SCATTERED_BLOCK_8DWORDS 2
|
||||
#define BRW_DATAPORT_DWORD_SCATTERED_BLOCK_16DWORDS 3
|
||||
|
||||
#define BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ 0
|
||||
#define BRW_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ 1
|
||||
#define BRW_DATAPORT_READ_MESSAGE_DWORD_BLOCK_READ 2
|
||||
#define BRW_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ 3
|
||||
|
||||
#define BRW_DATAPORT_READ_TARGET_DATA_CACHE 0
|
||||
#define BRW_DATAPORT_READ_TARGET_RENDER_CACHE 1
|
||||
#define BRW_DATAPORT_READ_TARGET_SAMPLER_CACHE 2
|
||||
|
||||
#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE 0
|
||||
#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED 1
|
||||
#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01 2
|
||||
#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN23 3
|
||||
#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01 4
|
||||
|
||||
#define BRW_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE 0
|
||||
#define BRW_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE 1
|
||||
#define BRW_DATAPORT_WRITE_MESSAGE_DWORD_BLOCK_WRITE 2
|
||||
#define BRW_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE 3
|
||||
#define BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE 4
|
||||
#define BRW_DATAPORT_WRITE_MESSAGE_STREAMED_VERTEX_BUFFER_WRITE 5
|
||||
#define BRW_DATAPORT_WRITE_MESSAGE_FLUSH_RENDER_CACHE 7
|
||||
|
||||
#define BRW_MATH_FUNCTION_INV 1
|
||||
#define BRW_MATH_FUNCTION_LOG 2
|
||||
#define BRW_MATH_FUNCTION_EXP 3
|
||||
#define BRW_MATH_FUNCTION_SQRT 4
|
||||
#define BRW_MATH_FUNCTION_RSQ 5
|
||||
#define BRW_MATH_FUNCTION_SIN 6 /* was 7 */
|
||||
#define BRW_MATH_FUNCTION_COS 7 /* was 8 */
|
||||
#define BRW_MATH_FUNCTION_SINCOS 8 /* was 6 */
|
||||
#define BRW_MATH_FUNCTION_TAN 9
|
||||
#define BRW_MATH_FUNCTION_POW 10
|
||||
#define BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER 11
|
||||
#define BRW_MATH_FUNCTION_INT_DIV_QUOTIENT 12
|
||||
#define BRW_MATH_FUNCTION_INT_DIV_REMAINDER 13
|
||||
|
||||
#define BRW_MATH_INTEGER_UNSIGNED 0
|
||||
#define BRW_MATH_INTEGER_SIGNED 1
|
||||
|
||||
#define BRW_MATH_PRECISION_FULL 0
|
||||
#define BRW_MATH_PRECISION_PARTIAL 1
|
||||
|
||||
#define BRW_MATH_SATURATE_NONE 0
|
||||
#define BRW_MATH_SATURATE_SATURATE 1
|
||||
|
||||
#define BRW_MATH_DATA_VECTOR 0
|
||||
#define BRW_MATH_DATA_SCALAR 1
|
||||
|
||||
#define BRW_URB_OPCODE_WRITE 0
|
||||
|
||||
#define BRW_URB_SWIZZLE_NONE 0
|
||||
#define BRW_URB_SWIZZLE_INTERLEAVE 1
|
||||
#define BRW_URB_SWIZZLE_TRANSPOSE 2
|
||||
|
||||
#define BRW_SCRATCH_SPACE_SIZE_1K 0
|
||||
#define BRW_SCRATCH_SPACE_SIZE_2K 1
|
||||
#define BRW_SCRATCH_SPACE_SIZE_4K 2
|
||||
#define BRW_SCRATCH_SPACE_SIZE_8K 3
|
||||
#define BRW_SCRATCH_SPACE_SIZE_16K 4
|
||||
#define BRW_SCRATCH_SPACE_SIZE_32K 5
|
||||
#define BRW_SCRATCH_SPACE_SIZE_64K 6
|
||||
#define BRW_SCRATCH_SPACE_SIZE_128K 7
|
||||
#define BRW_SCRATCH_SPACE_SIZE_256K 8
|
||||
#define BRW_SCRATCH_SPACE_SIZE_512K 9
|
||||
#define BRW_SCRATCH_SPACE_SIZE_1M 10
|
||||
#define BRW_SCRATCH_SPACE_SIZE_2M 11
|
||||
|
||||
|
||||
|
||||
|
||||
#define CMD_URB_FENCE 0x6000
|
||||
#define CMD_CS_URB_STATE 0x6001
|
||||
#define CMD_CONST_BUFFER 0x6002
|
||||
|
||||
#define CMD_STATE_BASE_ADDRESS 0x6101
|
||||
#define CMD_STATE_INSN_POINTER 0x6102
|
||||
#define CMD_PIPELINE_SELECT_965 0x6104
|
||||
#define CMD_PIPELINE_SELECT_GM45 0x6904
|
||||
|
||||
#define CMD_PIPELINED_STATE_POINTERS 0x7800
|
||||
#define CMD_BINDING_TABLE_PTRS 0x7801
|
||||
|
||||
#define CMD_VERTEX_BUFFER 0x7808
|
||||
# define BRW_VB0_INDEX_SHIFT 27
|
||||
# define BRW_VB0_ACCESS_VERTEXDATA (0 << 26)
|
||||
# define BRW_VB0_ACCESS_INSTANCEDATA (1 << 26)
|
||||
# define BRW_VB0_PITCH_SHIFT 0
|
||||
|
||||
#define CMD_VERTEX_ELEMENT 0x7809
|
||||
# define BRW_VE0_INDEX_SHIFT 27
|
||||
# define BRW_VE0_FORMAT_SHIFT 16
|
||||
# define BRW_VE0_VALID (1 << 26)
|
||||
# define BRW_VE0_SRC_OFFSET_SHIFT 0
|
||||
# define BRW_VE1_COMPONENT_NOSTORE 0
|
||||
# define BRW_VE1_COMPONENT_STORE_SRC 1
|
||||
# define BRW_VE1_COMPONENT_STORE_0 2
|
||||
# define BRW_VE1_COMPONENT_STORE_1_FLT 3
|
||||
# define BRW_VE1_COMPONENT_STORE_1_INT 4
|
||||
# define BRW_VE1_COMPONENT_STORE_VID 5
|
||||
# define BRW_VE1_COMPONENT_STORE_IID 6
|
||||
# define BRW_VE1_COMPONENT_STORE_PID 7
|
||||
# define BRW_VE1_COMPONENT_0_SHIFT 28
|
||||
# define BRW_VE1_COMPONENT_1_SHIFT 24
|
||||
# define BRW_VE1_COMPONENT_2_SHIFT 20
|
||||
# define BRW_VE1_COMPONENT_3_SHIFT 16
|
||||
# define BRW_VE1_DST_OFFSET_SHIFT 0
|
||||
|
||||
#define CMD_INDEX_BUFFER 0x780a
|
||||
#define CMD_VF_STATISTICS_965 0x780b
|
||||
#define CMD_VF_STATISTICS_GM45 0x680b
|
||||
|
||||
#define CMD_DRAW_RECT 0x7900
|
||||
#define CMD_BLEND_CONSTANT_COLOR 0x7901
|
||||
#define CMD_CHROMA_KEY 0x7904
|
||||
#define CMD_DEPTH_BUFFER 0x7905
|
||||
#define CMD_POLY_STIPPLE_OFFSET 0x7906
|
||||
#define CMD_POLY_STIPPLE_PATTERN 0x7907
|
||||
#define CMD_LINE_STIPPLE_PATTERN 0x7908
|
||||
#define CMD_GLOBAL_DEPTH_OFFSET_CLAMP 0x7909
|
||||
#define CMD_AA_LINE_PARAMETERS 0x790a
|
||||
|
||||
#define CMD_PIPE_CONTROL 0x7a00
|
||||
|
||||
#define CMD_3D_PRIM 0x7b00
|
||||
|
||||
#define CMD_MI_FLUSH 0x0200
|
||||
|
||||
|
||||
/* Various values from the R0 vertex header:
|
||||
*/
|
||||
#define R02_PRIM_END 0x1
|
||||
#define R02_PRIM_START 0x2
|
||||
|
||||
#define URB_SIZES(brw) (BRW_IS_IGDNG(brw) ? 1024 : \
|
||||
(BRW_IS_G4X(brw) ? 384 : 256)) /* 512 bit units */
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,922 @@
|
||||
/*
|
||||
* Copyright © 2008 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "brw_disasm.h"
|
||||
#include "brw_structs.h"
|
||||
#include "brw_reg.h"
|
||||
#include "brw_defines.h"
|
||||
|
||||
struct {
|
||||
char *name;
|
||||
int nsrc;
|
||||
int ndst;
|
||||
} opcode[128] = {
|
||||
[BRW_OPCODE_MOV] = { .name = "mov", .nsrc = 1, .ndst = 1 },
|
||||
[BRW_OPCODE_FRC] = { .name = "frc", .nsrc = 1, .ndst = 1 },
|
||||
[BRW_OPCODE_RNDU] = { .name = "rndu", .nsrc = 1, .ndst = 1 },
|
||||
[BRW_OPCODE_RNDD] = { .name = "rndd", .nsrc = 1, .ndst = 1 },
|
||||
[BRW_OPCODE_RNDE] = { .name = "rnde", .nsrc = 1, .ndst = 1 },
|
||||
[BRW_OPCODE_RNDZ] = { .name = "rndz", .nsrc = 1, .ndst = 1 },
|
||||
[BRW_OPCODE_NOT] = { .name = "not", .nsrc = 1, .ndst = 1 },
|
||||
[BRW_OPCODE_LZD] = { .name = "lzd", .nsrc = 1, .ndst = 1 },
|
||||
|
||||
[BRW_OPCODE_MUL] = { .name = "mul", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_MAC] = { .name = "mac", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_MACH] = { .name = "mach", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_LINE] = { .name = "line", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_SAD2] = { .name = "sad2", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_SADA2] = { .name = "sada2", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_DP4] = { .name = "dp4", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_DPH] = { .name = "dph", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_DP3] = { .name = "dp3", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_DP2] = { .name = "dp2", .nsrc = 2, .ndst = 1 },
|
||||
|
||||
[BRW_OPCODE_AVG] = { .name = "avg", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_ADD] = { .name = "add", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_SEL] = { .name = "sel", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_AND] = { .name = "and", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_OR] = { .name = "or", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_XOR] = { .name = "xor", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_SHR] = { .name = "shr", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_SHL] = { .name = "shl", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_ASR] = { .name = "asr", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_CMP] = { .name = "cmp", .nsrc = 2, .ndst = 1 },
|
||||
[BRW_OPCODE_CMPN] = { .name = "cmpn", .nsrc = 2, .ndst = 1 },
|
||||
|
||||
[BRW_OPCODE_SEND] = { .name = "send", .nsrc = 1, .ndst = 1 },
|
||||
[BRW_OPCODE_NOP] = { .name = "nop", .nsrc = 0, .ndst = 0 },
|
||||
[BRW_OPCODE_JMPI] = { .name = "jmpi", .nsrc = 1, .ndst = 0 },
|
||||
[BRW_OPCODE_IF] = { .name = "if", .nsrc = 2, .ndst = 0 },
|
||||
[BRW_OPCODE_IFF] = { .name = "iff", .nsrc = 1, .ndst = 01 },
|
||||
[BRW_OPCODE_WHILE] = { .name = "while", .nsrc = 1, .ndst = 0 },
|
||||
[BRW_OPCODE_ELSE] = { .name = "else", .nsrc = 2, .ndst = 0 },
|
||||
[BRW_OPCODE_BREAK] = { .name = "break", .nsrc = 1, .ndst = 0 },
|
||||
[BRW_OPCODE_CONTINUE] = { .name = "cont", .nsrc = 1, .ndst = 0 },
|
||||
[BRW_OPCODE_HALT] = { .name = "halt", .nsrc = 1, .ndst = 0 },
|
||||
[BRW_OPCODE_MSAVE] = { .name = "msave", .nsrc = 1, .ndst = 1 },
|
||||
[BRW_OPCODE_PUSH] = { .name = "push", .nsrc = 1, .ndst = 1 },
|
||||
[BRW_OPCODE_MRESTORE] = { .name = "mrest", .nsrc = 1, .ndst = 1 },
|
||||
[BRW_OPCODE_POP] = { .name = "pop", .nsrc = 2, .ndst = 0 },
|
||||
[BRW_OPCODE_WAIT] = { .name = "wait", .nsrc = 1, .ndst = 0 },
|
||||
[BRW_OPCODE_DO] = { .name = "do", .nsrc = 0, .ndst = 0 },
|
||||
[BRW_OPCODE_ENDIF] = { .name = "endif", .nsrc = 2, .ndst = 0 },
|
||||
};
|
||||
|
||||
char *conditional_modifier[16] = {
|
||||
[BRW_CONDITIONAL_NONE] = "",
|
||||
[BRW_CONDITIONAL_Z] = ".e",
|
||||
[BRW_CONDITIONAL_NZ] = ".ne",
|
||||
[BRW_CONDITIONAL_G] = ".g",
|
||||
[BRW_CONDITIONAL_GE] = ".ge",
|
||||
[BRW_CONDITIONAL_L] = ".l",
|
||||
[BRW_CONDITIONAL_LE] = ".le",
|
||||
[BRW_CONDITIONAL_R] = ".r",
|
||||
[BRW_CONDITIONAL_O] = ".o",
|
||||
[BRW_CONDITIONAL_U] = ".u",
|
||||
};
|
||||
|
||||
char *negate[2] = {
|
||||
[0] = "",
|
||||
[1] = "-",
|
||||
};
|
||||
|
||||
char *_abs[2] = {
|
||||
[0] = "",
|
||||
[1] = "(abs)",
|
||||
};
|
||||
|
||||
char *vert_stride[16] = {
|
||||
[0] = "0",
|
||||
[1] = "1",
|
||||
[2] = "2",
|
||||
[3] = "4",
|
||||
[4] = "8",
|
||||
[5] = "16",
|
||||
[6] = "32",
|
||||
[15] = "VxH",
|
||||
};
|
||||
|
||||
char *width[8] = {
|
||||
[0] = "1",
|
||||
[1] = "2",
|
||||
[2] = "4",
|
||||
[3] = "8",
|
||||
[4] = "16",
|
||||
};
|
||||
|
||||
char *horiz_stride[4] = {
|
||||
[0] = "0",
|
||||
[1] = "1",
|
||||
[2] = "2",
|
||||
[3] = "4"
|
||||
};
|
||||
|
||||
char *chan_sel[4] = {
|
||||
[0] = "x",
|
||||
[1] = "y",
|
||||
[2] = "z",
|
||||
[3] = "w",
|
||||
};
|
||||
|
||||
char *dest_condmod[16] = {
|
||||
[0] = NULL
|
||||
};
|
||||
|
||||
char *debug_ctrl[2] = {
|
||||
[0] = "",
|
||||
[1] = ".breakpoint"
|
||||
};
|
||||
|
||||
char *saturate[2] = {
|
||||
[0] = "",
|
||||
[1] = ".sat"
|
||||
};
|
||||
|
||||
char *exec_size[8] = {
|
||||
[0] = "1",
|
||||
[1] = "2",
|
||||
[2] = "4",
|
||||
[3] = "8",
|
||||
[4] = "16",
|
||||
[5] = "32"
|
||||
};
|
||||
|
||||
char *pred_inv[2] = {
|
||||
[0] = "+",
|
||||
[1] = "-"
|
||||
};
|
||||
|
||||
char *pred_ctrl_align16[16] = {
|
||||
[1] = "",
|
||||
[2] = ".x",
|
||||
[3] = ".y",
|
||||
[4] = ".z",
|
||||
[5] = ".w",
|
||||
[6] = ".any4h",
|
||||
[7] = ".all4h",
|
||||
};
|
||||
|
||||
char *pred_ctrl_align1[16] = {
|
||||
[1] = "",
|
||||
[2] = ".anyv",
|
||||
[3] = ".allv",
|
||||
[4] = ".any2h",
|
||||
[5] = ".all2h",
|
||||
[6] = ".any4h",
|
||||
[7] = ".all4h",
|
||||
[8] = ".any8h",
|
||||
[9] = ".all8h",
|
||||
[10] = ".any16h",
|
||||
[11] = ".all16h",
|
||||
};
|
||||
|
||||
char *thread_ctrl[4] = {
|
||||
[0] = "",
|
||||
[2] = "switch"
|
||||
};
|
||||
|
||||
char *compr_ctrl[4] = {
|
||||
[0] = "",
|
||||
[1] = "sechalf",
|
||||
[2] = "compr",
|
||||
};
|
||||
|
||||
char *dep_ctrl[4] = {
|
||||
[0] = "",
|
||||
[1] = "NoDDClr",
|
||||
[2] = "NoDDChk",
|
||||
[3] = "NoDDClr,NoDDChk",
|
||||
};
|
||||
|
||||
char *mask_ctrl[4] = {
|
||||
[0] = "",
|
||||
[1] = "nomask",
|
||||
};
|
||||
|
||||
char *access_mode[2] = {
|
||||
[0] = "align1",
|
||||
[1] = "align16",
|
||||
};
|
||||
|
||||
char *reg_encoding[8] = {
|
||||
[0] = "UD",
|
||||
[1] = "D",
|
||||
[2] = "UW",
|
||||
[3] = "W",
|
||||
[4] = "UB",
|
||||
[5] = "B",
|
||||
[7] = "F"
|
||||
};
|
||||
|
||||
char *imm_encoding[8] = {
|
||||
[0] = "UD",
|
||||
[1] = "D",
|
||||
[2] = "UW",
|
||||
[3] = "W",
|
||||
[5] = "VF",
|
||||
[5] = "V",
|
||||
[7] = "F"
|
||||
};
|
||||
|
||||
char *reg_file[4] = {
|
||||
[0] = "A",
|
||||
[1] = "g",
|
||||
[2] = "m",
|
||||
[3] = "imm",
|
||||
};
|
||||
|
||||
char *writemask[16] = {
|
||||
[0x0] = ".",
|
||||
[0x1] = ".x",
|
||||
[0x2] = ".y",
|
||||
[0x3] = ".xy",
|
||||
[0x4] = ".z",
|
||||
[0x5] = ".xz",
|
||||
[0x6] = ".yz",
|
||||
[0x7] = ".xyz",
|
||||
[0x8] = ".w",
|
||||
[0x9] = ".xw",
|
||||
[0xa] = ".yw",
|
||||
[0xb] = ".xyw",
|
||||
[0xc] = ".zw",
|
||||
[0xd] = ".xzw",
|
||||
[0xe] = ".yzw",
|
||||
[0xf] = "",
|
||||
};
|
||||
|
||||
char *end_of_thread[2] = {
|
||||
[0] = "",
|
||||
[1] = "EOT"
|
||||
};
|
||||
|
||||
char *target_function[16] = {
|
||||
[BRW_MESSAGE_TARGET_NULL] = "null",
|
||||
[BRW_MESSAGE_TARGET_MATH] = "math",
|
||||
[BRW_MESSAGE_TARGET_SAMPLER] = "sampler",
|
||||
[BRW_MESSAGE_TARGET_GATEWAY] = "gateway",
|
||||
[BRW_MESSAGE_TARGET_DATAPORT_READ] = "read",
|
||||
[BRW_MESSAGE_TARGET_DATAPORT_WRITE] = "write",
|
||||
[BRW_MESSAGE_TARGET_URB] = "urb",
|
||||
[BRW_MESSAGE_TARGET_THREAD_SPAWNER] = "thread_spawner"
|
||||
};
|
||||
|
||||
char *math_function[16] = {
|
||||
[BRW_MATH_FUNCTION_INV] = "inv",
|
||||
[BRW_MATH_FUNCTION_LOG] = "log",
|
||||
[BRW_MATH_FUNCTION_EXP] = "exp",
|
||||
[BRW_MATH_FUNCTION_SQRT] = "sqrt",
|
||||
[BRW_MATH_FUNCTION_RSQ] = "rsq",
|
||||
[BRW_MATH_FUNCTION_SIN] = "sin",
|
||||
[BRW_MATH_FUNCTION_COS] = "cos",
|
||||
[BRW_MATH_FUNCTION_SINCOS] = "sincos",
|
||||
[BRW_MATH_FUNCTION_TAN] = "tan",
|
||||
[BRW_MATH_FUNCTION_POW] = "pow",
|
||||
[BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod",
|
||||
[BRW_MATH_FUNCTION_INT_DIV_QUOTIENT] = "intmod",
|
||||
[BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intdiv",
|
||||
};
|
||||
|
||||
char *math_saturate[2] = {
|
||||
[0] = "",
|
||||
[1] = "sat"
|
||||
};
|
||||
|
||||
char *math_signed[2] = {
|
||||
[0] = "",
|
||||
[1] = "signed"
|
||||
};
|
||||
|
||||
char *math_scalar[2] = {
|
||||
[0] = "",
|
||||
[1] = "scalar"
|
||||
};
|
||||
|
||||
char *math_precision[2] = {
|
||||
[0] = "",
|
||||
[1] = "partial_precision"
|
||||
};
|
||||
|
||||
char *urb_swizzle[4] = {
|
||||
[BRW_URB_SWIZZLE_NONE] = "",
|
||||
[BRW_URB_SWIZZLE_INTERLEAVE] = "interleave",
|
||||
[BRW_URB_SWIZZLE_TRANSPOSE] = "transpose",
|
||||
};
|
||||
|
||||
char *urb_allocate[2] = {
|
||||
[0] = "",
|
||||
[1] = "allocate"
|
||||
};
|
||||
|
||||
char *urb_used[2] = {
|
||||
[0] = "",
|
||||
[1] = "used"
|
||||
};
|
||||
|
||||
char *urb_complete[2] = {
|
||||
[0] = "",
|
||||
[1] = "complete"
|
||||
};
|
||||
|
||||
char *sampler_target_format[4] = {
|
||||
[0] = "F",
|
||||
[2] = "UD",
|
||||
[3] = "D"
|
||||
};
|
||||
|
||||
|
||||
static int column;
|
||||
|
||||
static int string (FILE *file, char *string)
|
||||
{
|
||||
fputs (string, file);
|
||||
column += strlen (string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int format (FILE *f, char *format, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
|
||||
vsnprintf (buf, sizeof (buf) - 1, format, args);
|
||||
string (f, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int newline (FILE *f)
|
||||
{
|
||||
putc ('\n', f);
|
||||
column = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pad (FILE *f, int c)
|
||||
{
|
||||
do
|
||||
string (f, " ");
|
||||
while (column < c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int control (FILE *file, char *name, char *ctrl[], GLuint id, int *space)
|
||||
{
|
||||
if (!ctrl[id]) {
|
||||
fprintf (file, "*** invalid %s value %d ",
|
||||
name, id);
|
||||
return 1;
|
||||
}
|
||||
if (ctrl[id][0])
|
||||
{
|
||||
if (space && *space)
|
||||
string (file, " ");
|
||||
string (file, ctrl[id]);
|
||||
if (space)
|
||||
*space = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_opcode (FILE *file, int id)
|
||||
{
|
||||
if (!opcode[id].name) {
|
||||
format (file, "*** invalid opcode value %d ", id);
|
||||
return 1;
|
||||
}
|
||||
string (file, opcode[id].name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int reg (FILE *file, GLuint _reg_file, GLuint _reg_nr)
|
||||
{
|
||||
int err = 0;
|
||||
if (_reg_file == BRW_ARCHITECTURE_REGISTER_FILE) {
|
||||
switch (_reg_nr & 0xf0) {
|
||||
case BRW_ARF_NULL:
|
||||
string (file, "null");
|
||||
return -1;
|
||||
case BRW_ARF_ADDRESS:
|
||||
format (file, "a%d", _reg_nr & 0x0f);
|
||||
break;
|
||||
case BRW_ARF_ACCUMULATOR:
|
||||
format (file, "acc%d", _reg_nr & 0x0f);
|
||||
break;
|
||||
case BRW_ARF_MASK:
|
||||
format (file, "mask%d", _reg_nr & 0x0f);
|
||||
break;
|
||||
case BRW_ARF_MASK_STACK:
|
||||
format (file, "msd%d", _reg_nr & 0x0f);
|
||||
break;
|
||||
case BRW_ARF_STATE:
|
||||
format (file, "sr%d", _reg_nr & 0x0f);
|
||||
break;
|
||||
case BRW_ARF_CONTROL:
|
||||
format (file, "cr%d", _reg_nr & 0x0f);
|
||||
break;
|
||||
case BRW_ARF_NOTIFICATION_COUNT:
|
||||
format (file, "n%d", _reg_nr & 0x0f);
|
||||
break;
|
||||
case BRW_ARF_IP:
|
||||
string (file, "ip");
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
format (file, "ARF%d", _reg_nr);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
err |= control (file, "src reg file", reg_file, _reg_file, NULL);
|
||||
format (file, "%d", _reg_nr);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dest (FILE *file, const struct brw_instruction *inst)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (inst->header.access_mode == BRW_ALIGN_1)
|
||||
{
|
||||
if (inst->bits1.da1.dest_address_mode == BRW_ADDRESS_DIRECT)
|
||||
{
|
||||
err |= reg (file, inst->bits1.da1.dest_reg_file, inst->bits1.da1.dest_reg_nr);
|
||||
if (err == -1)
|
||||
return 0;
|
||||
if (inst->bits1.da1.dest_subreg_nr)
|
||||
format (file, ".%d", inst->bits1.da1.dest_subreg_nr);
|
||||
format (file, "<%d>", inst->bits1.da1.dest_horiz_stride);
|
||||
err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da1.dest_reg_type, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
string (file, "g[a0");
|
||||
if (inst->bits1.ia1.dest_subreg_nr)
|
||||
format (file, ".%d", inst->bits1.ia1.dest_subreg_nr);
|
||||
if (inst->bits1.ia1.dest_indirect_offset)
|
||||
format (file, " %d", inst->bits1.ia1.dest_indirect_offset);
|
||||
string (file, "]");
|
||||
format (file, "<%d>", inst->bits1.ia1.dest_horiz_stride);
|
||||
err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.ia1.dest_reg_type, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inst->bits1.da16.dest_address_mode == BRW_ADDRESS_DIRECT)
|
||||
{
|
||||
err |= reg (file, inst->bits1.da16.dest_reg_file, inst->bits1.da16.dest_reg_nr);
|
||||
if (err == -1)
|
||||
return 0;
|
||||
if (inst->bits1.da16.dest_subreg_nr)
|
||||
format (file, ".%d", inst->bits1.da16.dest_subreg_nr);
|
||||
string (file, "<1>");
|
||||
err |= control (file, "writemask", writemask, inst->bits1.da16.dest_writemask, NULL);
|
||||
err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da16.dest_reg_type, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = 1;
|
||||
string (file, "Indirect align16 address mode not supported");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int src_align1_region (FILE *file,
|
||||
GLuint _vert_stride, GLuint _width, GLuint _horiz_stride)
|
||||
{
|
||||
int err = 0;
|
||||
string (file, "<");
|
||||
err |= control (file, "vert stride", vert_stride, _vert_stride, NULL);
|
||||
string (file, ",");
|
||||
err |= control (file, "width", width, _width, NULL);
|
||||
string (file, ",");
|
||||
err |= control (file, "horiz_stride", horiz_stride, _horiz_stride, NULL);
|
||||
string (file, ">");
|
||||
return err;
|
||||
}
|
||||
|
||||
static int src_da1 (FILE *file, GLuint type, GLuint _reg_file,
|
||||
GLuint _vert_stride, GLuint _width, GLuint _horiz_stride,
|
||||
GLuint reg_num, GLuint sub_reg_num, GLuint __abs, GLuint _negate)
|
||||
{
|
||||
int err = 0;
|
||||
err |= control (file, "negate", negate, _negate, NULL);
|
||||
err |= control (file, "abs", _abs, __abs, NULL);
|
||||
|
||||
err |= reg (file, _reg_file, reg_num);
|
||||
if (err == -1)
|
||||
return 0;
|
||||
if (sub_reg_num)
|
||||
format (file, ".%d", sub_reg_num);
|
||||
src_align1_region (file, _vert_stride, _width, _horiz_stride);
|
||||
err |= control (file, "src reg encoding", reg_encoding, type, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int src_ia1 (FILE *file,
|
||||
GLuint type,
|
||||
GLuint _reg_file,
|
||||
GLint _addr_imm,
|
||||
GLuint _addr_subreg_nr,
|
||||
GLuint _negate,
|
||||
GLuint __abs,
|
||||
GLuint _addr_mode,
|
||||
GLuint _horiz_stride,
|
||||
GLuint _width,
|
||||
GLuint _vert_stride)
|
||||
{
|
||||
int err = 0;
|
||||
err |= control (file, "negate", negate, _negate, NULL);
|
||||
err |= control (file, "abs", _abs, __abs, NULL);
|
||||
|
||||
string (file, "g[a0");
|
||||
if (_addr_subreg_nr)
|
||||
format (file, ".%d", _addr_subreg_nr);
|
||||
if (_addr_imm)
|
||||
format (file, " %d", _addr_imm);
|
||||
string (file, "]");
|
||||
src_align1_region (file, _vert_stride, _width, _horiz_stride);
|
||||
err |= control (file, "src reg encoding", reg_encoding, type, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int src_da16 (FILE *file,
|
||||
GLuint _reg_type,
|
||||
GLuint _reg_file,
|
||||
GLuint _vert_stride,
|
||||
GLuint _reg_nr,
|
||||
GLuint _subreg_nr,
|
||||
GLuint __abs,
|
||||
GLuint _negate,
|
||||
GLuint swz_x,
|
||||
GLuint swz_y,
|
||||
GLuint swz_z,
|
||||
GLuint swz_w)
|
||||
{
|
||||
int err = 0;
|
||||
err |= control (file, "negate", negate, _negate, NULL);
|
||||
err |= control (file, "abs", _abs, __abs, NULL);
|
||||
|
||||
err |= reg (file, _reg_file, _reg_nr);
|
||||
if (err == -1)
|
||||
return 0;
|
||||
if (_subreg_nr)
|
||||
format (file, ".%d", _subreg_nr);
|
||||
string (file, "<");
|
||||
err |= control (file, "vert stride", vert_stride, _vert_stride, NULL);
|
||||
string (file, ",1,1>");
|
||||
err |= control (file, "src da16 reg type", reg_encoding, _reg_type, NULL);
|
||||
/*
|
||||
* Three kinds of swizzle display:
|
||||
* identity - nothing printed
|
||||
* 1->all - print the single channel
|
||||
* 1->1 - print the mapping
|
||||
*/
|
||||
if (swz_x == BRW_CHANNEL_X &&
|
||||
swz_y == BRW_CHANNEL_Y &&
|
||||
swz_z == BRW_CHANNEL_Z &&
|
||||
swz_w == BRW_CHANNEL_W)
|
||||
{
|
||||
;
|
||||
}
|
||||
else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w)
|
||||
{
|
||||
string (file, ".");
|
||||
err |= control (file, "channel select", chan_sel, swz_x, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
string (file, ".");
|
||||
err |= control (file, "channel select", chan_sel, swz_x, NULL);
|
||||
err |= control (file, "channel select", chan_sel, swz_y, NULL);
|
||||
err |= control (file, "channel select", chan_sel, swz_z, NULL);
|
||||
err |= control (file, "channel select", chan_sel, swz_w, NULL);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int imm (FILE *file, GLuint type, const struct brw_instruction *inst) {
|
||||
switch (type) {
|
||||
case BRW_REGISTER_TYPE_UD:
|
||||
format (file, "0x%08xUD", inst->bits3.ud);
|
||||
break;
|
||||
case BRW_REGISTER_TYPE_D:
|
||||
format (file, "%dD", inst->bits3.d);
|
||||
break;
|
||||
case BRW_REGISTER_TYPE_UW:
|
||||
format (file, "0x%04xUW", (uint16_t) inst->bits3.ud);
|
||||
break;
|
||||
case BRW_REGISTER_TYPE_W:
|
||||
format (file, "%dW", (int16_t) inst->bits3.d);
|
||||
break;
|
||||
case BRW_REGISTER_TYPE_UB:
|
||||
format (file, "0x%02xUB", (int8_t) inst->bits3.ud);
|
||||
break;
|
||||
case BRW_REGISTER_TYPE_VF:
|
||||
format (file, "Vector Float");
|
||||
break;
|
||||
case BRW_REGISTER_TYPE_V:
|
||||
format (file, "0x%08xV", inst->bits3.ud);
|
||||
break;
|
||||
case BRW_REGISTER_TYPE_F:
|
||||
format (file, "%-gF", inst->bits3.f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int src0 (FILE *file, const struct brw_instruction *inst)
|
||||
{
|
||||
if (inst->bits1.da1.src0_reg_file == BRW_IMMEDIATE_VALUE)
|
||||
return imm (file, inst->bits1.da1.src0_reg_type,
|
||||
inst);
|
||||
else if (inst->header.access_mode == BRW_ALIGN_1)
|
||||
{
|
||||
if (inst->bits2.da1.src0_address_mode == BRW_ADDRESS_DIRECT)
|
||||
{
|
||||
return src_da1 (file,
|
||||
inst->bits1.da1.src0_reg_type,
|
||||
inst->bits1.da1.src0_reg_file,
|
||||
inst->bits2.da1.src0_vert_stride,
|
||||
inst->bits2.da1.src0_width,
|
||||
inst->bits2.da1.src0_horiz_stride,
|
||||
inst->bits2.da1.src0_reg_nr,
|
||||
inst->bits2.da1.src0_subreg_nr,
|
||||
inst->bits2.da1.src0_abs,
|
||||
inst->bits2.da1.src0_negate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return src_ia1 (file,
|
||||
inst->bits1.ia1.src0_reg_type,
|
||||
inst->bits1.ia1.src0_reg_file,
|
||||
inst->bits2.ia1.src0_indirect_offset,
|
||||
inst->bits2.ia1.src0_subreg_nr,
|
||||
inst->bits2.ia1.src0_negate,
|
||||
inst->bits2.ia1.src0_abs,
|
||||
inst->bits2.ia1.src0_address_mode,
|
||||
inst->bits2.ia1.src0_horiz_stride,
|
||||
inst->bits2.ia1.src0_width,
|
||||
inst->bits2.ia1.src0_vert_stride);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inst->bits2.da16.src0_address_mode == BRW_ADDRESS_DIRECT)
|
||||
{
|
||||
return src_da16 (file,
|
||||
inst->bits1.da16.src0_reg_type,
|
||||
inst->bits1.da16.src0_reg_file,
|
||||
inst->bits2.da16.src0_vert_stride,
|
||||
inst->bits2.da16.src0_reg_nr,
|
||||
inst->bits2.da16.src0_subreg_nr,
|
||||
inst->bits2.da16.src0_abs,
|
||||
inst->bits2.da16.src0_negate,
|
||||
inst->bits2.da16.src0_swz_x,
|
||||
inst->bits2.da16.src0_swz_y,
|
||||
inst->bits2.da16.src0_swz_z,
|
||||
inst->bits2.da16.src0_swz_w);
|
||||
}
|
||||
else
|
||||
{
|
||||
string (file, "Indirect align16 address mode not supported");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int src1 (FILE *file, const struct brw_instruction *inst)
|
||||
{
|
||||
if (inst->bits1.da1.src1_reg_file == BRW_IMMEDIATE_VALUE)
|
||||
return imm (file, inst->bits1.da1.src1_reg_type,
|
||||
inst);
|
||||
else if (inst->header.access_mode == BRW_ALIGN_1)
|
||||
{
|
||||
if (inst->bits3.da1.src1_address_mode == BRW_ADDRESS_DIRECT)
|
||||
{
|
||||
return src_da1 (file,
|
||||
inst->bits1.da1.src1_reg_type,
|
||||
inst->bits1.da1.src1_reg_file,
|
||||
inst->bits3.da1.src1_vert_stride,
|
||||
inst->bits3.da1.src1_width,
|
||||
inst->bits3.da1.src1_horiz_stride,
|
||||
inst->bits3.da1.src1_reg_nr,
|
||||
inst->bits3.da1.src1_subreg_nr,
|
||||
inst->bits3.da1.src1_abs,
|
||||
inst->bits3.da1.src1_negate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return src_ia1 (file,
|
||||
inst->bits1.ia1.src1_reg_type,
|
||||
inst->bits1.ia1.src1_reg_file,
|
||||
inst->bits3.ia1.src1_indirect_offset,
|
||||
inst->bits3.ia1.src1_subreg_nr,
|
||||
inst->bits3.ia1.src1_negate,
|
||||
inst->bits3.ia1.src1_abs,
|
||||
inst->bits3.ia1.src1_address_mode,
|
||||
inst->bits3.ia1.src1_horiz_stride,
|
||||
inst->bits3.ia1.src1_width,
|
||||
inst->bits3.ia1.src1_vert_stride);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inst->bits3.da16.src1_address_mode == BRW_ADDRESS_DIRECT)
|
||||
{
|
||||
return src_da16 (file,
|
||||
inst->bits1.da16.src1_reg_type,
|
||||
inst->bits1.da16.src1_reg_file,
|
||||
inst->bits3.da16.src1_vert_stride,
|
||||
inst->bits3.da16.src1_reg_nr,
|
||||
inst->bits3.da16.src1_subreg_nr,
|
||||
inst->bits3.da16.src1_abs,
|
||||
inst->bits3.da16.src1_negate,
|
||||
inst->bits3.da16.src1_swz_x,
|
||||
inst->bits3.da16.src1_swz_y,
|
||||
inst->bits3.da16.src1_swz_z,
|
||||
inst->bits3.da16.src1_swz_w);
|
||||
}
|
||||
else
|
||||
{
|
||||
string (file, "Indirect align16 address mode not supported");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int brw_disasm_insn (FILE *file, const struct brw_instruction *inst)
|
||||
{
|
||||
int err = 0;
|
||||
int space = 0;
|
||||
|
||||
if (inst->header.predicate_control) {
|
||||
string (file, "(");
|
||||
err |= control (file, "predicate inverse", pred_inv, inst->header.predicate_inverse, NULL);
|
||||
string (file, "f0");
|
||||
if (inst->bits2.da1.flag_reg_nr)
|
||||
format (file, ".%d", inst->bits2.da1.flag_reg_nr);
|
||||
if (inst->header.access_mode == BRW_ALIGN_1)
|
||||
err |= control (file, "predicate control align1", pred_ctrl_align1,
|
||||
inst->header.predicate_control, NULL);
|
||||
else
|
||||
err |= control (file, "predicate control align16", pred_ctrl_align16,
|
||||
inst->header.predicate_control, NULL);
|
||||
string (file, ") ");
|
||||
}
|
||||
|
||||
err |= print_opcode (file, inst->header.opcode);
|
||||
err |= control (file, "saturate", saturate, inst->header.saturate, NULL);
|
||||
err |= control (file, "debug control", debug_ctrl, inst->header.debug_control, NULL);
|
||||
|
||||
if (inst->header.opcode != BRW_OPCODE_SEND)
|
||||
err |= control (file, "conditional modifier", conditional_modifier,
|
||||
inst->header.destreg__conditionalmod, NULL);
|
||||
|
||||
if (inst->header.opcode != BRW_OPCODE_NOP) {
|
||||
string (file, "(");
|
||||
err |= control (file, "execution size", exec_size, inst->header.execution_size, NULL);
|
||||
string (file, ")");
|
||||
}
|
||||
|
||||
if (inst->header.opcode == BRW_OPCODE_SEND)
|
||||
format (file, " %d", inst->header.destreg__conditionalmod);
|
||||
|
||||
if (opcode[inst->header.opcode].ndst > 0) {
|
||||
pad (file, 16);
|
||||
err |= dest (file, inst);
|
||||
}
|
||||
if (opcode[inst->header.opcode].nsrc > 0) {
|
||||
pad (file, 32);
|
||||
err |= src0 (file, inst);
|
||||
}
|
||||
if (opcode[inst->header.opcode].nsrc > 1) {
|
||||
pad (file, 48);
|
||||
err |= src1 (file, inst);
|
||||
}
|
||||
|
||||
if (inst->header.opcode == BRW_OPCODE_SEND) {
|
||||
newline (file);
|
||||
pad (file, 16);
|
||||
space = 0;
|
||||
err |= control (file, "target function", target_function,
|
||||
inst->bits3.generic.msg_target, &space);
|
||||
switch (inst->bits3.generic.msg_target) {
|
||||
case BRW_MESSAGE_TARGET_MATH:
|
||||
err |= control (file, "math function", math_function,
|
||||
inst->bits3.math.function, &space);
|
||||
err |= control (file, "math saturate", math_saturate,
|
||||
inst->bits3.math.saturate, &space);
|
||||
err |= control (file, "math signed", math_signed,
|
||||
inst->bits3.math.int_type, &space);
|
||||
err |= control (file, "math scalar", math_scalar,
|
||||
inst->bits3.math.data_type, &space);
|
||||
err |= control (file, "math precision", math_precision,
|
||||
inst->bits3.math.precision, &space);
|
||||
break;
|
||||
case BRW_MESSAGE_TARGET_SAMPLER:
|
||||
format (file, " (%d, %d, ",
|
||||
inst->bits3.sampler.binding_table_index,
|
||||
inst->bits3.sampler.sampler);
|
||||
err |= control (file, "sampler target format", sampler_target_format,
|
||||
inst->bits3.sampler.return_format, NULL);
|
||||
string (file, ")");
|
||||
break;
|
||||
case BRW_MESSAGE_TARGET_DATAPORT_WRITE:
|
||||
format (file, " (%d, %d, %d, %d)",
|
||||
inst->bits3.dp_write.binding_table_index,
|
||||
(inst->bits3.dp_write.pixel_scoreboard_clear << 3) |
|
||||
inst->bits3.dp_write.msg_control,
|
||||
inst->bits3.dp_write.msg_type,
|
||||
inst->bits3.dp_write.send_commit_msg);
|
||||
break;
|
||||
case BRW_MESSAGE_TARGET_URB:
|
||||
format (file, " %d", inst->bits3.urb.offset);
|
||||
space = 1;
|
||||
err |= control (file, "urb swizzle", urb_swizzle,
|
||||
inst->bits3.urb.swizzle_control, &space);
|
||||
err |= control (file, "urb allocate", urb_allocate,
|
||||
inst->bits3.urb.allocate, &space);
|
||||
err |= control (file, "urb used", urb_used,
|
||||
inst->bits3.urb.used, &space);
|
||||
err |= control (file, "urb complete", urb_complete,
|
||||
inst->bits3.urb.complete, &space);
|
||||
break;
|
||||
case BRW_MESSAGE_TARGET_THREAD_SPAWNER:
|
||||
break;
|
||||
default:
|
||||
format (file, "unsupported target %d", inst->bits3.generic.msg_target);
|
||||
break;
|
||||
}
|
||||
if (space)
|
||||
string (file, " ");
|
||||
format (file, "mlen %d",
|
||||
inst->bits3.generic.msg_length);
|
||||
format (file, " rlen %d",
|
||||
inst->bits3.generic.response_length);
|
||||
}
|
||||
pad (file, 64);
|
||||
if (inst->header.opcode != BRW_OPCODE_NOP) {
|
||||
string (file, "{");
|
||||
space = 1;
|
||||
err |= control(file, "access mode", access_mode, inst->header.access_mode, &space);
|
||||
err |= control (file, "mask control", mask_ctrl, inst->header.mask_control, &space);
|
||||
err |= control (file, "dependency control", dep_ctrl, inst->header.dependency_control, &space);
|
||||
err |= control (file, "compression control", compr_ctrl, inst->header.compression_control, &space);
|
||||
err |= control (file, "thread control", thread_ctrl, inst->header.thread_control, &space);
|
||||
if (inst->header.opcode == BRW_OPCODE_SEND)
|
||||
err |= control (file, "end of thread", end_of_thread,
|
||||
inst->bits3.generic.end_of_thread, &space);
|
||||
if (space)
|
||||
string (file, " ");
|
||||
string (file, "}");
|
||||
}
|
||||
string (file, ";");
|
||||
newline (file);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int brw_disasm (FILE *file,
|
||||
const struct brw_instruction *inst,
|
||||
unsigned count)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
err = brw_disasm_insn(stderr, &inst[i]);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
fprintf(file, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright © 2008 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BRW_DISASM_H
|
||||
#define BRW_DISASM_H
|
||||
|
||||
struct brw_instruction;
|
||||
|
||||
int brw_disasm_insn (FILE *file, const struct brw_instruction *inst);
|
||||
int brw_disasm (FILE *file,
|
||||
const struct brw_instruction *inst,
|
||||
unsigned count);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,291 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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 "util/u_prim.h"
|
||||
#include "util/u_upload_mgr.h"
|
||||
|
||||
#include "brw_draw.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_debug.h"
|
||||
#include "brw_screen.h"
|
||||
|
||||
#include "brw_batchbuffer.h"
|
||||
|
||||
|
||||
static uint32_t prim_to_hw_prim[PIPE_PRIM_POLYGON+1] = {
|
||||
_3DPRIM_POINTLIST,
|
||||
_3DPRIM_LINELIST,
|
||||
_3DPRIM_LINELOOP,
|
||||
_3DPRIM_LINESTRIP,
|
||||
_3DPRIM_TRILIST,
|
||||
_3DPRIM_TRISTRIP,
|
||||
_3DPRIM_TRIFAN,
|
||||
_3DPRIM_QUADLIST,
|
||||
_3DPRIM_QUADSTRIP,
|
||||
_3DPRIM_POLYGON
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* When the primitive changes, set a state bit and re-validate. Not
|
||||
* the nicest and would rather deal with this by having all the
|
||||
* programs be immune to the active primitive (ie. cope with all
|
||||
* possibilities). That may not be realistic however.
|
||||
*/
|
||||
static int brw_set_prim(struct brw_context *brw, unsigned prim )
|
||||
{
|
||||
|
||||
if (BRW_DEBUG & DEBUG_PRIMS)
|
||||
debug_printf("PRIM: %s\n", u_prim_name(prim));
|
||||
|
||||
if (prim != brw->primitive) {
|
||||
unsigned reduced_prim;
|
||||
|
||||
brw->primitive = prim;
|
||||
brw->state.dirty.brw |= BRW_NEW_PRIMITIVE;
|
||||
|
||||
reduced_prim = u_reduced_prim(prim);
|
||||
if (reduced_prim != brw->reduced_primitive) {
|
||||
brw->reduced_primitive = reduced_prim;
|
||||
brw->state.dirty.brw |= BRW_NEW_REDUCED_PRIMITIVE;
|
||||
}
|
||||
}
|
||||
|
||||
return prim_to_hw_prim[prim];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int brw_emit_prim(struct brw_context *brw,
|
||||
unsigned start,
|
||||
unsigned count,
|
||||
boolean indexed,
|
||||
uint32_t hw_prim)
|
||||
{
|
||||
struct brw_3d_primitive prim_packet;
|
||||
int ret;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_PRIMS)
|
||||
debug_printf("%s start %d count %d indexed %d hw_prim %d\n",
|
||||
__FUNCTION__, start, count, indexed, hw_prim);
|
||||
|
||||
prim_packet.header.opcode = CMD_3D_PRIM;
|
||||
prim_packet.header.length = sizeof(prim_packet)/4 - 2;
|
||||
prim_packet.header.pad = 0;
|
||||
prim_packet.header.topology = hw_prim;
|
||||
prim_packet.header.indexed = indexed;
|
||||
|
||||
prim_packet.verts_per_instance = count;
|
||||
prim_packet.start_vert_location = start;
|
||||
if (indexed)
|
||||
prim_packet.start_vert_location += brw->ib.start_vertex_offset;
|
||||
prim_packet.instance_count = 1;
|
||||
prim_packet.start_instance_location = 0;
|
||||
prim_packet.base_vert_location = 0; /* prim->basevertex; XXX: add this to gallium */
|
||||
|
||||
|
||||
/* If we're set to always flush, do it before and after the primitive emit.
|
||||
* We want to catch both missed flushes that hurt instruction/state cache
|
||||
* and missed flushes of the render cache as it heads to other parts of
|
||||
* the besides the draw code.
|
||||
*/
|
||||
if (0) {
|
||||
BEGIN_BATCH(1, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH((CMD_MI_FLUSH << 16) | BRW_FLUSH_STATE_CACHE);
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
if (prim_packet.verts_per_instance) {
|
||||
ret = brw_batchbuffer_data( brw->batch, &prim_packet,
|
||||
sizeof(prim_packet), LOOP_CLIPRECTS);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (0) {
|
||||
BEGIN_BATCH(1, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH((CMD_MI_FLUSH << 16) | BRW_FLUSH_STATE_CACHE);
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* May fail if out of video memory for texture or vbo upload, or on
|
||||
* fallback conditions.
|
||||
*/
|
||||
static int
|
||||
try_draw_range_elements(struct brw_context *brw,
|
||||
struct pipe_buffer *index_buffer,
|
||||
unsigned hw_prim,
|
||||
unsigned start, unsigned count)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = brw_validate_state(brw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Check that we can fit our state in with our existing batchbuffer, or
|
||||
* flush otherwise.
|
||||
*/
|
||||
ret = brw->sws->check_aperture_space(brw->sws,
|
||||
brw->state.validated_bos,
|
||||
brw->state.validated_bo_count);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = brw_upload_state(brw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = brw_emit_prim(brw, start, count, index_buffer != NULL, hw_prim);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (brw->flags.always_flush_batch)
|
||||
brw_context_flush( brw );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static boolean
|
||||
brw_draw_range_elements(struct pipe_context *pipe,
|
||||
struct pipe_buffer *index_buffer,
|
||||
unsigned index_size,
|
||||
unsigned min_index,
|
||||
unsigned max_index,
|
||||
unsigned mode, unsigned start, unsigned count)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
int ret;
|
||||
uint32_t hw_prim;
|
||||
|
||||
hw_prim = brw_set_prim(brw, mode);
|
||||
|
||||
if (BRW_DEBUG & DEBUG_PRIMS)
|
||||
debug_printf("PRIM: %s start %d count %d index_buffer %p\n",
|
||||
u_prim_name(mode), start, count, (void *)index_buffer);
|
||||
|
||||
/* Potentially trigger upload of new index buffer.
|
||||
*
|
||||
* XXX: do we need to go through state validation to achieve this?
|
||||
* Could just call upload code directly.
|
||||
*/
|
||||
if (brw->curr.index_buffer != index_buffer ||
|
||||
brw->curr.index_size != index_size) {
|
||||
pipe_buffer_reference( &brw->curr.index_buffer, index_buffer );
|
||||
brw->curr.index_size = index_size;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_INDEX_BUFFER;
|
||||
}
|
||||
|
||||
/* XXX: do we really care?
|
||||
*/
|
||||
if (brw->curr.min_index != min_index ||
|
||||
brw->curr.max_index != max_index)
|
||||
{
|
||||
brw->curr.min_index = min_index;
|
||||
brw->curr.max_index = max_index;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_INDEX_RANGE;
|
||||
}
|
||||
|
||||
|
||||
/* Make a first attempt at drawing:
|
||||
*/
|
||||
ret = try_draw_range_elements(brw, index_buffer, hw_prim, start, count );
|
||||
|
||||
/* Otherwise, flush and retry:
|
||||
*/
|
||||
if (ret != 0) {
|
||||
brw_context_flush( brw );
|
||||
ret = try_draw_range_elements(brw, index_buffer, hw_prim, start, count );
|
||||
assert(ret == 0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static boolean
|
||||
brw_draw_elements(struct pipe_context *pipe,
|
||||
struct pipe_buffer *index_buffer,
|
||||
unsigned index_size,
|
||||
unsigned mode,
|
||||
unsigned start, unsigned count)
|
||||
{
|
||||
return brw_draw_range_elements( pipe, index_buffer,
|
||||
index_size,
|
||||
0, 0xffffffff,
|
||||
mode,
|
||||
start, count );
|
||||
}
|
||||
|
||||
static boolean
|
||||
brw_draw_arrays(struct pipe_context *pipe, unsigned mode,
|
||||
unsigned start, unsigned count)
|
||||
{
|
||||
return brw_draw_elements(pipe, NULL, 0, mode, start, count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
boolean brw_draw_init( struct brw_context *brw )
|
||||
{
|
||||
/* Register our drawing function:
|
||||
*/
|
||||
brw->base.draw_arrays = brw_draw_arrays;
|
||||
brw->base.draw_elements = brw_draw_elements;
|
||||
brw->base.draw_range_elements = brw_draw_range_elements;
|
||||
|
||||
/* Create helpers for uploading data in user buffers:
|
||||
*/
|
||||
brw->vb.upload_vertex = u_upload_create( brw->base.screen,
|
||||
128 * 1024,
|
||||
64,
|
||||
PIPE_BUFFER_USAGE_VERTEX );
|
||||
if (brw->vb.upload_vertex == NULL)
|
||||
return FALSE;
|
||||
|
||||
brw->vb.upload_index = u_upload_create( brw->base.screen,
|
||||
32 * 1024,
|
||||
64,
|
||||
PIPE_BUFFER_USAGE_INDEX );
|
||||
if (brw->vb.upload_index == NULL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void brw_draw_cleanup( struct brw_context *brw )
|
||||
{
|
||||
u_upload_destroy( brw->vb.upload_vertex );
|
||||
u_upload_destroy( brw->vb.upload_index );
|
||||
|
||||
bo_reference(&brw->ib.bo, NULL);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2005 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef BRW_DRAW_H
|
||||
#define BRW_DRAW_H
|
||||
|
||||
#include "brw_types.h"
|
||||
|
||||
struct brw_context;
|
||||
|
||||
boolean brw_draw_init( struct brw_context *brw );
|
||||
void brw_draw_cleanup( struct brw_context *brw );
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,542 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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 "pipe/p_context.h"
|
||||
|
||||
#include "util/u_upload_mgr.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "brw_draw.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_screen.h"
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_debug.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static unsigned brw_translate_surface_format( unsigned id )
|
||||
{
|
||||
switch (id) {
|
||||
case PIPE_FORMAT_R64_FLOAT:
|
||||
return BRW_SURFACEFORMAT_R64_FLOAT;
|
||||
case PIPE_FORMAT_R64G64_FLOAT:
|
||||
return BRW_SURFACEFORMAT_R64G64_FLOAT;
|
||||
case PIPE_FORMAT_R64G64B64_FLOAT:
|
||||
return BRW_SURFACEFORMAT_R64G64B64_FLOAT;
|
||||
case PIPE_FORMAT_R64G64B64A64_FLOAT:
|
||||
return BRW_SURFACEFORMAT_R64G64B64A64_FLOAT;
|
||||
|
||||
case PIPE_FORMAT_R32_FLOAT:
|
||||
return BRW_SURFACEFORMAT_R32_FLOAT;
|
||||
case PIPE_FORMAT_R32G32_FLOAT:
|
||||
return BRW_SURFACEFORMAT_R32G32_FLOAT;
|
||||
case PIPE_FORMAT_R32G32B32_FLOAT:
|
||||
return BRW_SURFACEFORMAT_R32G32B32_FLOAT;
|
||||
case PIPE_FORMAT_R32G32B32A32_FLOAT:
|
||||
return BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
|
||||
|
||||
case PIPE_FORMAT_R32_UNORM:
|
||||
return BRW_SURFACEFORMAT_R32_UNORM;
|
||||
case PIPE_FORMAT_R32G32_UNORM:
|
||||
return BRW_SURFACEFORMAT_R32G32_UNORM;
|
||||
case PIPE_FORMAT_R32G32B32_UNORM:
|
||||
return BRW_SURFACEFORMAT_R32G32B32_UNORM;
|
||||
case PIPE_FORMAT_R32G32B32A32_UNORM:
|
||||
return BRW_SURFACEFORMAT_R32G32B32A32_UNORM;
|
||||
|
||||
case PIPE_FORMAT_R32_USCALED:
|
||||
return BRW_SURFACEFORMAT_R32_USCALED;
|
||||
case PIPE_FORMAT_R32G32_USCALED:
|
||||
return BRW_SURFACEFORMAT_R32G32_USCALED;
|
||||
case PIPE_FORMAT_R32G32B32_USCALED:
|
||||
return BRW_SURFACEFORMAT_R32G32B32_USCALED;
|
||||
case PIPE_FORMAT_R32G32B32A32_USCALED:
|
||||
return BRW_SURFACEFORMAT_R32G32B32A32_USCALED;
|
||||
|
||||
case PIPE_FORMAT_R32_SNORM:
|
||||
return BRW_SURFACEFORMAT_R32_SNORM;
|
||||
case PIPE_FORMAT_R32G32_SNORM:
|
||||
return BRW_SURFACEFORMAT_R32G32_SNORM;
|
||||
case PIPE_FORMAT_R32G32B32_SNORM:
|
||||
return BRW_SURFACEFORMAT_R32G32B32_SNORM;
|
||||
case PIPE_FORMAT_R32G32B32A32_SNORM:
|
||||
return BRW_SURFACEFORMAT_R32G32B32A32_SNORM;
|
||||
|
||||
case PIPE_FORMAT_R32_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R32_SSCALED;
|
||||
case PIPE_FORMAT_R32G32_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R32G32_SSCALED;
|
||||
case PIPE_FORMAT_R32G32B32_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R32G32B32_SSCALED;
|
||||
case PIPE_FORMAT_R32G32B32A32_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R32G32B32A32_SSCALED;
|
||||
|
||||
case PIPE_FORMAT_R16_UNORM:
|
||||
return BRW_SURFACEFORMAT_R16_UNORM;
|
||||
case PIPE_FORMAT_R16G16_UNORM:
|
||||
return BRW_SURFACEFORMAT_R16G16_UNORM;
|
||||
case PIPE_FORMAT_R16G16B16_UNORM:
|
||||
return BRW_SURFACEFORMAT_R16G16B16_UNORM;
|
||||
case PIPE_FORMAT_R16G16B16A16_UNORM:
|
||||
return BRW_SURFACEFORMAT_R16G16B16A16_UNORM;
|
||||
|
||||
case PIPE_FORMAT_R16_USCALED:
|
||||
return BRW_SURFACEFORMAT_R16_USCALED;
|
||||
case PIPE_FORMAT_R16G16_USCALED:
|
||||
return BRW_SURFACEFORMAT_R16G16_USCALED;
|
||||
case PIPE_FORMAT_R16G16B16_USCALED:
|
||||
return BRW_SURFACEFORMAT_R16G16B16_USCALED;
|
||||
case PIPE_FORMAT_R16G16B16A16_USCALED:
|
||||
return BRW_SURFACEFORMAT_R16G16B16A16_USCALED;
|
||||
|
||||
case PIPE_FORMAT_R16_SNORM:
|
||||
return BRW_SURFACEFORMAT_R16_SNORM;
|
||||
case PIPE_FORMAT_R16G16_SNORM:
|
||||
return BRW_SURFACEFORMAT_R16G16_SNORM;
|
||||
case PIPE_FORMAT_R16G16B16_SNORM:
|
||||
return BRW_SURFACEFORMAT_R16G16B16_SNORM;
|
||||
case PIPE_FORMAT_R16G16B16A16_SNORM:
|
||||
return BRW_SURFACEFORMAT_R16G16B16A16_SNORM;
|
||||
|
||||
case PIPE_FORMAT_R16_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R16_SSCALED;
|
||||
case PIPE_FORMAT_R16G16_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R16G16_SSCALED;
|
||||
case PIPE_FORMAT_R16G16B16_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R16G16B16_SSCALED;
|
||||
case PIPE_FORMAT_R16G16B16A16_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R16G16B16A16_SSCALED;
|
||||
|
||||
case PIPE_FORMAT_R8_UNORM:
|
||||
return BRW_SURFACEFORMAT_R8_UNORM;
|
||||
case PIPE_FORMAT_R8G8_UNORM:
|
||||
return BRW_SURFACEFORMAT_R8G8_UNORM;
|
||||
case PIPE_FORMAT_R8G8B8_UNORM:
|
||||
return BRW_SURFACEFORMAT_R8G8B8_UNORM;
|
||||
case PIPE_FORMAT_R8G8B8A8_UNORM:
|
||||
return BRW_SURFACEFORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
case PIPE_FORMAT_R8_USCALED:
|
||||
return BRW_SURFACEFORMAT_R8_USCALED;
|
||||
case PIPE_FORMAT_R8G8_USCALED:
|
||||
return BRW_SURFACEFORMAT_R8G8_USCALED;
|
||||
case PIPE_FORMAT_R8G8B8_USCALED:
|
||||
return BRW_SURFACEFORMAT_R8G8B8_USCALED;
|
||||
case PIPE_FORMAT_R8G8B8A8_USCALED:
|
||||
return BRW_SURFACEFORMAT_R8G8B8A8_USCALED;
|
||||
|
||||
case PIPE_FORMAT_R8_SNORM:
|
||||
return BRW_SURFACEFORMAT_R8_SNORM;
|
||||
case PIPE_FORMAT_R8G8_SNORM:
|
||||
return BRW_SURFACEFORMAT_R8G8_SNORM;
|
||||
case PIPE_FORMAT_R8G8B8_SNORM:
|
||||
return BRW_SURFACEFORMAT_R8G8B8_SNORM;
|
||||
case PIPE_FORMAT_R8G8B8A8_SNORM:
|
||||
return BRW_SURFACEFORMAT_R8G8B8A8_SNORM;
|
||||
|
||||
case PIPE_FORMAT_R8_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R8_SSCALED;
|
||||
case PIPE_FORMAT_R8G8_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R8G8_SSCALED;
|
||||
case PIPE_FORMAT_R8G8B8_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R8G8B8_SSCALED;
|
||||
case PIPE_FORMAT_R8G8B8A8_SSCALED:
|
||||
return BRW_SURFACEFORMAT_R8G8B8A8_SSCALED;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned get_index_type(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case 1: return BRW_INDEX_BYTE;
|
||||
case 2: return BRW_INDEX_WORD;
|
||||
case 4: return BRW_INDEX_DWORD;
|
||||
default: assert(0); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int brw_prepare_vertices(struct brw_context *brw)
|
||||
{
|
||||
unsigned int min_index = brw->curr.min_index;
|
||||
unsigned int max_index = brw->curr.max_index;
|
||||
GLuint i;
|
||||
int ret;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_VERTS)
|
||||
debug_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
|
||||
|
||||
|
||||
for (i = 0; i < brw->curr.num_vertex_buffers; i++) {
|
||||
struct pipe_vertex_buffer *vb = &brw->curr.vertex_buffer[i];
|
||||
struct brw_winsys_buffer *bo;
|
||||
struct pipe_buffer *upload_buf = NULL;
|
||||
unsigned offset;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_VERTS)
|
||||
debug_printf("%s vb[%d] user:%d offset:0x%x sz:0x%x stride:0x%x\n",
|
||||
__FUNCTION__, i,
|
||||
brw_buffer_is_user_buffer(vb->buffer),
|
||||
vb->buffer_offset,
|
||||
vb->buffer->size,
|
||||
vb->stride);
|
||||
|
||||
if (brw_buffer_is_user_buffer(vb->buffer)) {
|
||||
|
||||
/* XXX: simplify this. Stop the state trackers from generating
|
||||
* zero-stride buffers & have them use additional constants (or
|
||||
* add support for >1 constant buffer) instead.
|
||||
*/
|
||||
unsigned size = (vb->stride == 0 ?
|
||||
vb->buffer->size - vb->buffer_offset :
|
||||
MAX2(vb->buffer->size - vb->buffer_offset,
|
||||
vb->stride * (max_index + 1 - min_index)));
|
||||
|
||||
ret = u_upload_buffer( brw->vb.upload_vertex,
|
||||
vb->buffer_offset + min_index * vb->stride,
|
||||
size,
|
||||
vb->buffer,
|
||||
&offset,
|
||||
&upload_buf );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bo = brw_buffer(upload_buf)->bo;
|
||||
|
||||
assert(offset + size <= bo->size);
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = vb->buffer_offset;
|
||||
bo = brw_buffer(vb->buffer)->bo;
|
||||
}
|
||||
|
||||
assert(offset < bo->size);
|
||||
|
||||
/* Set up post-upload info about this vertex buffer:
|
||||
*/
|
||||
brw->vb.vb[i].offset = offset;
|
||||
brw->vb.vb[i].stride = vb->stride;
|
||||
brw->vb.vb[i].vertex_count = (vb->stride == 0 ?
|
||||
1 :
|
||||
(bo->size - offset) / vb->stride);
|
||||
|
||||
bo_reference( &brw->vb.vb[i].bo, bo );
|
||||
|
||||
/* Don't need to retain this reference. We have a reference on
|
||||
* the underlying winsys buffer:
|
||||
*/
|
||||
pipe_buffer_reference( &upload_buf, NULL );
|
||||
}
|
||||
|
||||
brw->vb.nr_vb = i;
|
||||
brw_prepare_query_begin(brw);
|
||||
|
||||
for (i = 0; i < brw->vb.nr_vb; i++) {
|
||||
brw_add_validated_bo(brw, brw->vb.vb[i].bo);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int brw_emit_vertex_buffers( struct brw_context *brw )
|
||||
{
|
||||
int i;
|
||||
|
||||
/* If the VS doesn't read any inputs (calculating vertex position from
|
||||
* a state variable for some reason, for example), just bail.
|
||||
*
|
||||
* The stale VB state stays in place, but they don't do anything unless
|
||||
* a VE loads from them.
|
||||
*/
|
||||
if (brw->vb.nr_vb == 0) {
|
||||
if (BRW_DEBUG & DEBUG_VERTS)
|
||||
debug_printf("%s: no active vertex buffers\n", __FUNCTION__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Emit VB state packets.
|
||||
*/
|
||||
BEGIN_BATCH(1 + brw->vb.nr_vb * 4, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH((CMD_VERTEX_BUFFER << 16) |
|
||||
((1 + brw->vb.nr_vb * 4) - 2));
|
||||
|
||||
for (i = 0; i < brw->vb.nr_vb; i++) {
|
||||
OUT_BATCH((i << BRW_VB0_INDEX_SHIFT) |
|
||||
BRW_VB0_ACCESS_VERTEXDATA |
|
||||
(brw->vb.vb[i].stride << BRW_VB0_PITCH_SHIFT));
|
||||
OUT_RELOC(brw->vb.vb[i].bo,
|
||||
BRW_USAGE_VERTEX,
|
||||
brw->vb.vb[i].offset);
|
||||
if (BRW_IS_IGDNG(brw)) {
|
||||
OUT_RELOC(brw->vb.vb[i].bo,
|
||||
BRW_USAGE_VERTEX,
|
||||
brw->vb.vb[i].bo->size - 1);
|
||||
} else
|
||||
OUT_BATCH(brw->vb.vb[i].stride ? brw->vb.vb[i].vertex_count : 0);
|
||||
OUT_BATCH(0); /* Instance data step rate */
|
||||
}
|
||||
ADVANCE_BATCH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int brw_emit_vertex_elements(struct brw_context *brw)
|
||||
{
|
||||
GLuint nr = brw->curr.num_vertex_elements;
|
||||
GLuint i;
|
||||
|
||||
brw_emit_query_begin(brw);
|
||||
|
||||
/* If the VS doesn't read any inputs (calculating vertex position from
|
||||
* a state variable for some reason, for example), emit a single pad
|
||||
* VERTEX_ELEMENT struct and bail.
|
||||
*
|
||||
* The stale VB state stays in place, but they don't do anything unless
|
||||
* a VE loads from them.
|
||||
*/
|
||||
if (nr == 0) {
|
||||
BEGIN_BATCH(3, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | 1);
|
||||
OUT_BATCH((0 << BRW_VE0_INDEX_SHIFT) |
|
||||
BRW_VE0_VALID |
|
||||
(BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) |
|
||||
(0 << BRW_VE0_SRC_OFFSET_SHIFT));
|
||||
OUT_BATCH((BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_0_SHIFT) |
|
||||
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) |
|
||||
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
|
||||
(BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT));
|
||||
ADVANCE_BATCH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now emit vertex element (VEP) state packets.
|
||||
*
|
||||
*/
|
||||
BEGIN_BATCH(1 + nr * 2, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH((CMD_VERTEX_ELEMENT << 16) | ((1 + nr * 2) - 2));
|
||||
for (i = 0; i < nr; i++) {
|
||||
const struct pipe_vertex_element *input = &brw->curr.vertex_element[i];
|
||||
uint32_t format = brw_translate_surface_format( input->src_format );
|
||||
uint32_t comp0 = BRW_VE1_COMPONENT_STORE_SRC;
|
||||
uint32_t comp1 = BRW_VE1_COMPONENT_STORE_SRC;
|
||||
uint32_t comp2 = BRW_VE1_COMPONENT_STORE_SRC;
|
||||
uint32_t comp3 = BRW_VE1_COMPONENT_STORE_SRC;
|
||||
|
||||
switch (input->nr_components) {
|
||||
case 0: comp0 = BRW_VE1_COMPONENT_STORE_0;
|
||||
case 1: comp1 = BRW_VE1_COMPONENT_STORE_0;
|
||||
case 2: comp2 = BRW_VE1_COMPONENT_STORE_0;
|
||||
case 3: comp3 = BRW_VE1_COMPONENT_STORE_1_FLT;
|
||||
break;
|
||||
}
|
||||
|
||||
OUT_BATCH((input->vertex_buffer_index << BRW_VE0_INDEX_SHIFT) |
|
||||
BRW_VE0_VALID |
|
||||
(format << BRW_VE0_FORMAT_SHIFT) |
|
||||
(input->src_offset << BRW_VE0_SRC_OFFSET_SHIFT));
|
||||
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
|
||||
(comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
|
||||
(comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
|
||||
(comp3 << BRW_VE1_COMPONENT_3_SHIFT));
|
||||
else
|
||||
OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
|
||||
(comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
|
||||
(comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
|
||||
(comp3 << BRW_VE1_COMPONENT_3_SHIFT) |
|
||||
((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
|
||||
}
|
||||
ADVANCE_BATCH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int brw_emit_vertices( struct brw_context *brw )
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = brw_emit_vertex_buffers( brw );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = brw_emit_vertex_elements( brw );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const struct brw_tracked_state brw_vertices = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_INDEX_RANGE |
|
||||
PIPE_NEW_VERTEX_BUFFER),
|
||||
.brw = BRW_NEW_BATCH,
|
||||
.cache = 0,
|
||||
},
|
||||
.prepare = brw_prepare_vertices,
|
||||
.emit = brw_emit_vertices,
|
||||
};
|
||||
|
||||
|
||||
static int brw_prepare_indices(struct brw_context *brw)
|
||||
{
|
||||
struct pipe_buffer *index_buffer = brw->curr.index_buffer;
|
||||
struct pipe_buffer *upload_buf = NULL;
|
||||
struct brw_winsys_buffer *bo = NULL;
|
||||
GLuint offset;
|
||||
GLuint index_size;
|
||||
GLuint ib_size;
|
||||
int ret;
|
||||
|
||||
if (index_buffer == NULL)
|
||||
return 0;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_VERTS)
|
||||
debug_printf("%s: index_size:%d index_buffer->size:%d\n",
|
||||
__FUNCTION__,
|
||||
brw->curr.index_size,
|
||||
brw->curr.index_buffer->size);
|
||||
|
||||
ib_size = index_buffer->size;
|
||||
index_size = brw->curr.index_size;
|
||||
|
||||
/* Turn userbuffer into a proper hardware buffer?
|
||||
*/
|
||||
if (brw_buffer_is_user_buffer(index_buffer)) {
|
||||
|
||||
ret = u_upload_buffer( brw->vb.upload_index,
|
||||
0,
|
||||
ib_size,
|
||||
index_buffer,
|
||||
&offset,
|
||||
&upload_buf );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bo = brw_buffer(upload_buf)->bo;
|
||||
|
||||
/* XXX: annotate the userbuffer with the upload information so
|
||||
* that successive calls don't get re-uploaded.
|
||||
*/
|
||||
}
|
||||
else {
|
||||
bo = brw_buffer(index_buffer)->bo;
|
||||
ib_size = bo->size;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
/* Use CMD_3D_PRIM's start_vertex_offset to avoid re-uploading the
|
||||
* index buffer state when we're just moving the start index of our
|
||||
* drawing.
|
||||
*
|
||||
* In gallium this will happen in the case where successive draw
|
||||
* calls are made with (distinct?) userbuffers, but the upload_mgr
|
||||
* places the data into a single winsys buffer.
|
||||
*
|
||||
* This statechange doesn't raise any state flags and is always
|
||||
* just merged into the final draw packet:
|
||||
*/
|
||||
if (1) {
|
||||
assert((offset & (index_size - 1)) == 0);
|
||||
brw->ib.start_vertex_offset = offset / index_size;
|
||||
}
|
||||
|
||||
/* These statechanges trigger a new CMD_INDEX_BUFFER packet:
|
||||
*/
|
||||
if (brw->ib.bo != bo ||
|
||||
brw->ib.size != ib_size)
|
||||
{
|
||||
bo_reference(&brw->ib.bo, bo);
|
||||
brw->ib.size = ib_size;
|
||||
brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER;
|
||||
}
|
||||
|
||||
pipe_buffer_reference( &upload_buf, NULL );
|
||||
brw_add_validated_bo(brw, brw->ib.bo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_indices = {
|
||||
.dirty = {
|
||||
.mesa = PIPE_NEW_INDEX_BUFFER,
|
||||
.brw = 0,
|
||||
.cache = 0,
|
||||
},
|
||||
.prepare = brw_prepare_indices,
|
||||
};
|
||||
|
||||
static int brw_emit_index_buffer(struct brw_context *brw)
|
||||
{
|
||||
/* Emit the indexbuffer packet:
|
||||
*/
|
||||
if (brw->ib.bo)
|
||||
{
|
||||
struct brw_indexbuffer ib;
|
||||
|
||||
memset(&ib, 0, sizeof(ib));
|
||||
|
||||
ib.header.bits.opcode = CMD_INDEX_BUFFER;
|
||||
ib.header.bits.length = sizeof(ib)/4 - 2;
|
||||
ib.header.bits.index_format = get_index_type(brw->ib.size);
|
||||
ib.header.bits.cut_index_enable = 0;
|
||||
|
||||
BEGIN_BATCH(4, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH( ib.header.dword );
|
||||
OUT_RELOC(brw->ib.bo,
|
||||
BRW_USAGE_VERTEX,
|
||||
brw->ib.offset);
|
||||
OUT_RELOC(brw->ib.bo,
|
||||
BRW_USAGE_VERTEX,
|
||||
brw->ib.offset + brw->ib.size - 1);
|
||||
OUT_BATCH( 0 );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_index_buffer = {
|
||||
.dirty = {
|
||||
.mesa = 0,
|
||||
.brw = BRW_NEW_BATCH | BRW_NEW_INDEX_BUFFER,
|
||||
.cache = 0,
|
||||
},
|
||||
.emit = brw_emit_index_buffer,
|
||||
};
|
||||
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_eu.h"
|
||||
|
||||
|
||||
|
||||
/* How does predicate control work when execution_size != 8? Do I
|
||||
* need to test/set for 0xffff when execution_size is 16?
|
||||
*/
|
||||
void brw_set_predicate_control_flag_value( struct brw_compile *p, GLuint value )
|
||||
{
|
||||
p->current->header.predicate_control = BRW_PREDICATE_NONE;
|
||||
|
||||
if (value != 0xff) {
|
||||
if (value != p->flag_value) {
|
||||
brw_push_insn_state(p);
|
||||
brw_MOV(p, brw_flag_reg(), brw_imm_uw(value));
|
||||
p->flag_value = value;
|
||||
brw_pop_insn_state(p);
|
||||
}
|
||||
|
||||
p->current->header.predicate_control = BRW_PREDICATE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
void brw_set_predicate_control( struct brw_compile *p, GLuint pc )
|
||||
{
|
||||
p->current->header.predicate_control = pc;
|
||||
}
|
||||
|
||||
void brw_set_conditionalmod( struct brw_compile *p, GLuint conditional )
|
||||
{
|
||||
p->current->header.destreg__conditionalmod = conditional;
|
||||
}
|
||||
|
||||
void brw_set_access_mode( struct brw_compile *p, GLuint access_mode )
|
||||
{
|
||||
p->current->header.access_mode = access_mode;
|
||||
}
|
||||
|
||||
void brw_set_compression_control( struct brw_compile *p, GLboolean compression_control )
|
||||
{
|
||||
p->current->header.compression_control = compression_control;
|
||||
}
|
||||
|
||||
void brw_set_mask_control( struct brw_compile *p, GLuint value )
|
||||
{
|
||||
p->current->header.mask_control = value;
|
||||
}
|
||||
|
||||
void brw_set_saturate( struct brw_compile *p, GLuint value )
|
||||
{
|
||||
p->current->header.saturate = value;
|
||||
}
|
||||
|
||||
void brw_push_insn_state( struct brw_compile *p )
|
||||
{
|
||||
assert(p->current != &p->stack[BRW_EU_MAX_INSN_STACK-1]);
|
||||
memcpy(p->current+1, p->current, sizeof(struct brw_instruction));
|
||||
p->current++;
|
||||
}
|
||||
|
||||
void brw_pop_insn_state( struct brw_compile *p )
|
||||
{
|
||||
assert(p->current != p->stack);
|
||||
p->current--;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*/
|
||||
void brw_init_compile( struct brw_context *brw, struct brw_compile *p )
|
||||
{
|
||||
p->brw = brw;
|
||||
p->nr_insn = 0;
|
||||
p->current = p->stack;
|
||||
memset(p->current, 0, sizeof(p->current[0]));
|
||||
|
||||
/* Some defaults?
|
||||
*/
|
||||
brw_set_mask_control(p, BRW_MASK_ENABLE); /* what does this do? */
|
||||
brw_set_saturate(p, 0);
|
||||
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
|
||||
brw_set_predicate_control_flag_value(p, 0xff);
|
||||
}
|
||||
|
||||
|
||||
enum pipe_error brw_get_program( struct brw_compile *p,
|
||||
const GLuint **data,
|
||||
GLuint *sz )
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
brw_NOP(p);
|
||||
|
||||
/* Is the generated program malformed for some reason?
|
||||
*/
|
||||
if (p->error)
|
||||
return PIPE_ERROR_BAD_INPUT;
|
||||
|
||||
*sz = p->nr_insn * sizeof(struct brw_instruction);
|
||||
*data = (const GLuint *)p->store;
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Subroutine calls require special attention.
|
||||
* Mesa instructions may be expanded into multiple hardware instructions
|
||||
* so the prog_instruction::BranchTarget field can't be used as an index
|
||||
* into the hardware instructions.
|
||||
*
|
||||
* The BranchTarget field isn't needed, however. Mesa's GLSL compiler
|
||||
* emits CAL and BGNSUB instructions with labels that can be used to map
|
||||
* subroutine calls to actual subroutine code blocks.
|
||||
*
|
||||
* The structures and function here implement patching of CAL instructions
|
||||
* so they jump to the right subroutine code...
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* For each OPCODE_BGNSUB we create one of these.
|
||||
*/
|
||||
struct brw_eu_label
|
||||
{
|
||||
GLuint label; /**< the label number */
|
||||
GLuint position; /**< the position of the brw instruction for this label */
|
||||
struct brw_eu_label *next; /**< next in linked list */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* For each OPCODE_CAL we create one of these.
|
||||
*/
|
||||
struct brw_eu_call
|
||||
{
|
||||
GLuint call_inst_pos; /**< location of the CAL instruction */
|
||||
GLuint label;
|
||||
struct brw_eu_call *next; /**< next in linked list */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called for each OPCODE_BGNSUB.
|
||||
*/
|
||||
void
|
||||
brw_save_label(struct brw_compile *c, unsigned l, GLuint position)
|
||||
{
|
||||
struct brw_eu_label *label = CALLOC_STRUCT(brw_eu_label);
|
||||
label->label = l;
|
||||
label->position = position;
|
||||
label->next = c->first_label;
|
||||
c->first_label = label;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called for each OPCODE_CAL.
|
||||
*/
|
||||
void
|
||||
brw_save_call(struct brw_compile *c, GLuint label, GLuint call_pos)
|
||||
{
|
||||
struct brw_eu_call *call = CALLOC_STRUCT(brw_eu_call);
|
||||
call->call_inst_pos = call_pos;
|
||||
call->label = label;
|
||||
call->next = c->first_call;
|
||||
c->first_call = call;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lookup a label, return label's position/offset.
|
||||
*/
|
||||
static GLuint
|
||||
brw_lookup_label(struct brw_compile *c, unsigned l)
|
||||
{
|
||||
const struct brw_eu_label *label;
|
||||
for (label = c->first_label; label; label = label->next) {
|
||||
if (l == label->label) {
|
||||
return label->position;
|
||||
}
|
||||
}
|
||||
abort(); /* should never happen */
|
||||
return ~0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When we're done generating code, this function is called to resolve
|
||||
* subroutine calls.
|
||||
*/
|
||||
void
|
||||
brw_resolve_cals(struct brw_compile *c)
|
||||
{
|
||||
const struct brw_eu_call *call;
|
||||
|
||||
for (call = c->first_call; call; call = call->next) {
|
||||
const GLuint sub_loc = brw_lookup_label(c, call->label);
|
||||
struct brw_instruction *brw_call_inst = &c->store[call->call_inst_pos];
|
||||
struct brw_instruction *brw_sub_inst = &c->store[sub_loc];
|
||||
GLint offset = brw_sub_inst - brw_call_inst;
|
||||
|
||||
/* patch brw_inst1 to point to brw_inst2 */
|
||||
brw_set_src1(brw_call_inst, brw_imm_d(offset * 16));
|
||||
}
|
||||
|
||||
/* free linked list of calls */
|
||||
{
|
||||
struct brw_eu_call *call, *next;
|
||||
for (call = c->first_call; call; call = next) {
|
||||
next = call->next;
|
||||
FREE(call);
|
||||
}
|
||||
c->first_call = NULL;
|
||||
}
|
||||
|
||||
/* free linked list of labels */
|
||||
{
|
||||
struct brw_eu_label *label, *next;
|
||||
for (label = c->first_label; label; label = next) {
|
||||
next = label->next;
|
||||
FREE(label);
|
||||
}
|
||||
c->first_label = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,992 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BRW_EU_H
|
||||
#define BRW_EU_H
|
||||
|
||||
#include "util/u_debug.h"
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
#include "brw_structs.h"
|
||||
#include "brw_defines.h"
|
||||
|
||||
#define BRW_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6))
|
||||
#define BRW_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3)
|
||||
|
||||
#define BRW_SWIZZLE_NOOP BRW_SWIZZLE4(0,1,2,3)
|
||||
#define BRW_SWIZZLE_XYZW BRW_SWIZZLE4(0,1,2,3)
|
||||
#define BRW_SWIZZLE_XXXX BRW_SWIZZLE4(0,0,0,0)
|
||||
#define BRW_SWIZZLE_XYXY BRW_SWIZZLE4(0,1,0,1)
|
||||
|
||||
#define BRW_WRITEMASK_NONE 0x00
|
||||
#define BRW_WRITEMASK_X 0x01
|
||||
#define BRW_WRITEMASK_Y 0x02
|
||||
#define BRW_WRITEMASK_XY 0x03
|
||||
#define BRW_WRITEMASK_Z 0x04
|
||||
#define BRW_WRITEMASK_XZ 0x05
|
||||
#define BRW_WRITEMASK_YZ 0x06
|
||||
#define BRW_WRITEMASK_XYZ 0x07
|
||||
#define BRW_WRITEMASK_W 0x08
|
||||
#define BRW_WRITEMASK_XW 0x09
|
||||
#define BRW_WRITEMASK_YW 0x0A
|
||||
#define BRW_WRITEMASK_XYW 0x0B
|
||||
#define BRW_WRITEMASK_ZW 0x0C
|
||||
#define BRW_WRITEMASK_XZW 0x0D
|
||||
#define BRW_WRITEMASK_YZW 0x0E
|
||||
#define BRW_WRITEMASK_XYZW 0x0F
|
||||
|
||||
|
||||
#define REG_SIZE (8*4)
|
||||
|
||||
|
||||
/* These aren't hardware structs, just something useful for us to pass around:
|
||||
*
|
||||
* Align1 operation has a lot of control over input ranges. Used in
|
||||
* WM programs to implement shaders decomposed into "channel serial"
|
||||
* or "structure of array" form:
|
||||
*/
|
||||
struct brw_reg
|
||||
{
|
||||
GLuint type:4;
|
||||
GLuint file:2;
|
||||
GLuint nr:8;
|
||||
GLuint subnr:5; /* :1 in align16 */
|
||||
GLuint negate:1; /* source only */
|
||||
GLuint abs:1; /* source only */
|
||||
GLuint vstride:4; /* source only */
|
||||
GLuint width:3; /* src only, align1 only */
|
||||
GLuint hstride:2; /* align1 only */
|
||||
GLuint address_mode:1; /* relative addressing, hopefully! */
|
||||
GLuint pad0:1;
|
||||
|
||||
union {
|
||||
struct {
|
||||
GLuint swizzle:8; /* src only, align16 only */
|
||||
GLuint writemask:4; /* dest only, align16 only */
|
||||
GLint indirect_offset:10; /* relative addressing offset */
|
||||
GLuint pad1:10; /* two dwords total */
|
||||
} bits;
|
||||
|
||||
GLfloat f;
|
||||
GLint d;
|
||||
GLuint ud;
|
||||
} dw1;
|
||||
};
|
||||
|
||||
|
||||
struct brw_indirect {
|
||||
GLuint addr_subnr:4;
|
||||
GLint addr_offset:10;
|
||||
GLuint pad:18;
|
||||
};
|
||||
|
||||
|
||||
struct brw_eu_label;
|
||||
struct brw_eu_call;
|
||||
|
||||
|
||||
|
||||
#define BRW_EU_MAX_INSN_STACK 5
|
||||
#define BRW_EU_MAX_INSN 10000
|
||||
|
||||
struct brw_compile {
|
||||
struct brw_instruction store[BRW_EU_MAX_INSN];
|
||||
GLuint nr_insn;
|
||||
|
||||
/* Allow clients to push/pop instruction state:
|
||||
*/
|
||||
struct brw_instruction stack[BRW_EU_MAX_INSN_STACK];
|
||||
struct brw_instruction *current;
|
||||
|
||||
GLuint flag_value;
|
||||
GLboolean single_program_flow;
|
||||
struct brw_context *brw;
|
||||
|
||||
struct brw_eu_label *first_label; /**< linked list of labels */
|
||||
struct brw_eu_call *first_call; /**< linked list of CALs */
|
||||
|
||||
boolean error;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
brw_save_label(struct brw_compile *c, unsigned label, GLuint position);
|
||||
|
||||
void
|
||||
brw_save_call(struct brw_compile *c, unsigned label, GLuint call_pos);
|
||||
|
||||
void
|
||||
brw_resolve_cals(struct brw_compile *c);
|
||||
|
||||
|
||||
|
||||
static INLINE int type_sz( GLuint type )
|
||||
{
|
||||
switch( type ) {
|
||||
case BRW_REGISTER_TYPE_UD:
|
||||
case BRW_REGISTER_TYPE_D:
|
||||
case BRW_REGISTER_TYPE_F:
|
||||
return 4;
|
||||
case BRW_REGISTER_TYPE_HF:
|
||||
case BRW_REGISTER_TYPE_UW:
|
||||
case BRW_REGISTER_TYPE_W:
|
||||
return 2;
|
||||
case BRW_REGISTER_TYPE_UB:
|
||||
case BRW_REGISTER_TYPE_B:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a brw_reg.
|
||||
* \param file one of the BRW_x_REGISTER_FILE values
|
||||
* \param nr register number/index
|
||||
* \param subnr register sub number
|
||||
* \param type one of BRW_REGISTER_TYPE_x
|
||||
* \param vstride one of BRW_VERTICAL_STRIDE_x
|
||||
* \param width one of BRW_WIDTH_x
|
||||
* \param hstride one of BRW_HORIZONTAL_STRIDE_x
|
||||
* \param swizzle one of BRW_SWIZZLE_x
|
||||
* \param writemask BRW_WRITEMASK_X/Y/Z/W bitfield
|
||||
*/
|
||||
static INLINE struct brw_reg brw_reg( GLuint file,
|
||||
GLuint nr,
|
||||
GLuint subnr,
|
||||
GLuint type,
|
||||
GLuint vstride,
|
||||
GLuint width,
|
||||
GLuint hstride,
|
||||
GLuint swizzle,
|
||||
GLuint writemask )
|
||||
{
|
||||
struct brw_reg reg;
|
||||
if (type == BRW_GENERAL_REGISTER_FILE)
|
||||
assert(nr < BRW_MAX_GRF);
|
||||
else if (type == BRW_MESSAGE_REGISTER_FILE)
|
||||
assert(nr < BRW_MAX_MRF);
|
||||
else if (type == BRW_ARCHITECTURE_REGISTER_FILE)
|
||||
assert(nr <= BRW_ARF_IP);
|
||||
|
||||
reg.type = type;
|
||||
reg.file = file;
|
||||
reg.nr = nr;
|
||||
reg.subnr = subnr * type_sz(type);
|
||||
reg.negate = 0;
|
||||
reg.abs = 0;
|
||||
reg.vstride = vstride;
|
||||
reg.width = width;
|
||||
reg.hstride = hstride;
|
||||
reg.address_mode = BRW_ADDRESS_DIRECT;
|
||||
reg.pad0 = 0;
|
||||
|
||||
/* Could do better: If the reg is r5.3<0;1,0>, we probably want to
|
||||
* set swizzle and writemask to W, as the lower bits of subnr will
|
||||
* be lost when converted to align16. This is probably too much to
|
||||
* keep track of as you'd want it adjusted by suboffset(), etc.
|
||||
* Perhaps fix up when converting to align16?
|
||||
*/
|
||||
reg.dw1.bits.swizzle = swizzle;
|
||||
reg.dw1.bits.writemask = writemask;
|
||||
reg.dw1.bits.indirect_offset = 0;
|
||||
reg.dw1.bits.pad1 = 0;
|
||||
return reg;
|
||||
}
|
||||
|
||||
/** Construct float[16] register */
|
||||
static INLINE struct brw_reg brw_vec16_reg( GLuint file,
|
||||
GLuint nr,
|
||||
GLuint subnr )
|
||||
{
|
||||
return brw_reg(file,
|
||||
nr,
|
||||
subnr,
|
||||
BRW_REGISTER_TYPE_F,
|
||||
BRW_VERTICAL_STRIDE_16,
|
||||
BRW_WIDTH_16,
|
||||
BRW_HORIZONTAL_STRIDE_1,
|
||||
BRW_SWIZZLE_XYZW,
|
||||
BRW_WRITEMASK_XYZW);
|
||||
}
|
||||
|
||||
/** Construct float[8] register */
|
||||
static INLINE struct brw_reg brw_vec8_reg( GLuint file,
|
||||
GLuint nr,
|
||||
GLuint subnr )
|
||||
{
|
||||
return brw_reg(file,
|
||||
nr,
|
||||
subnr,
|
||||
BRW_REGISTER_TYPE_F,
|
||||
BRW_VERTICAL_STRIDE_8,
|
||||
BRW_WIDTH_8,
|
||||
BRW_HORIZONTAL_STRIDE_1,
|
||||
BRW_SWIZZLE_XYZW,
|
||||
BRW_WRITEMASK_XYZW);
|
||||
}
|
||||
|
||||
/** Construct float[4] register */
|
||||
static INLINE struct brw_reg brw_vec4_reg( GLuint file,
|
||||
GLuint nr,
|
||||
GLuint subnr )
|
||||
{
|
||||
return brw_reg(file,
|
||||
nr,
|
||||
subnr,
|
||||
BRW_REGISTER_TYPE_F,
|
||||
BRW_VERTICAL_STRIDE_4,
|
||||
BRW_WIDTH_4,
|
||||
BRW_HORIZONTAL_STRIDE_1,
|
||||
BRW_SWIZZLE_XYZW,
|
||||
BRW_WRITEMASK_XYZW);
|
||||
}
|
||||
|
||||
/** Construct float[2] register */
|
||||
static INLINE struct brw_reg brw_vec2_reg( GLuint file,
|
||||
GLuint nr,
|
||||
GLuint subnr )
|
||||
{
|
||||
return brw_reg(file,
|
||||
nr,
|
||||
subnr,
|
||||
BRW_REGISTER_TYPE_F,
|
||||
BRW_VERTICAL_STRIDE_2,
|
||||
BRW_WIDTH_2,
|
||||
BRW_HORIZONTAL_STRIDE_1,
|
||||
BRW_SWIZZLE_XYXY,
|
||||
BRW_WRITEMASK_XY);
|
||||
}
|
||||
|
||||
/** Construct float[1] register */
|
||||
static INLINE struct brw_reg brw_vec1_reg( GLuint file,
|
||||
GLuint nr,
|
||||
GLuint subnr )
|
||||
{
|
||||
return brw_reg(file,
|
||||
nr,
|
||||
subnr,
|
||||
BRW_REGISTER_TYPE_F,
|
||||
BRW_VERTICAL_STRIDE_0,
|
||||
BRW_WIDTH_1,
|
||||
BRW_HORIZONTAL_STRIDE_0,
|
||||
BRW_SWIZZLE_XXXX,
|
||||
BRW_WRITEMASK_X);
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct brw_reg retype( struct brw_reg reg,
|
||||
GLuint type )
|
||||
{
|
||||
reg.type = type;
|
||||
return reg;
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg suboffset( struct brw_reg reg,
|
||||
GLuint delta )
|
||||
{
|
||||
reg.subnr += delta * type_sz(reg.type);
|
||||
return reg;
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct brw_reg offset( struct brw_reg reg,
|
||||
GLuint delta )
|
||||
{
|
||||
reg.nr += delta;
|
||||
return reg;
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct brw_reg byte_offset( struct brw_reg reg,
|
||||
GLuint bytes )
|
||||
{
|
||||
GLuint newoffset = reg.nr * REG_SIZE + reg.subnr + bytes;
|
||||
reg.nr = newoffset / REG_SIZE;
|
||||
reg.subnr = newoffset % REG_SIZE;
|
||||
return reg;
|
||||
}
|
||||
|
||||
|
||||
/** Construct unsigned word[16] register */
|
||||
static INLINE struct brw_reg brw_uw16_reg( GLuint file,
|
||||
GLuint nr,
|
||||
GLuint subnr )
|
||||
{
|
||||
return suboffset(retype(brw_vec16_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
|
||||
}
|
||||
|
||||
/** Construct unsigned word[8] register */
|
||||
static INLINE struct brw_reg brw_uw8_reg( GLuint file,
|
||||
GLuint nr,
|
||||
GLuint subnr )
|
||||
{
|
||||
return suboffset(retype(brw_vec8_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
|
||||
}
|
||||
|
||||
/** Construct unsigned word[1] register */
|
||||
static INLINE struct brw_reg brw_uw1_reg( GLuint file,
|
||||
GLuint nr,
|
||||
GLuint subnr )
|
||||
{
|
||||
return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg brw_imm_reg( GLuint type )
|
||||
{
|
||||
return brw_reg( BRW_IMMEDIATE_VALUE,
|
||||
0,
|
||||
0,
|
||||
type,
|
||||
BRW_VERTICAL_STRIDE_0,
|
||||
BRW_WIDTH_1,
|
||||
BRW_HORIZONTAL_STRIDE_0,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
|
||||
/** Construct float immediate register */
|
||||
static INLINE struct brw_reg brw_imm_f( GLfloat f )
|
||||
{
|
||||
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F);
|
||||
imm.dw1.f = f;
|
||||
return imm;
|
||||
}
|
||||
|
||||
/** Construct integer immediate register */
|
||||
static INLINE struct brw_reg brw_imm_d( GLint d )
|
||||
{
|
||||
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D);
|
||||
imm.dw1.d = d;
|
||||
return imm;
|
||||
}
|
||||
|
||||
/** Construct uint immediate register */
|
||||
static INLINE struct brw_reg brw_imm_ud( GLuint ud )
|
||||
{
|
||||
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD);
|
||||
imm.dw1.ud = ud;
|
||||
return imm;
|
||||
}
|
||||
|
||||
/** Construct ushort immediate register */
|
||||
static INLINE struct brw_reg brw_imm_uw( GLushort uw )
|
||||
{
|
||||
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW);
|
||||
imm.dw1.ud = uw | (uw << 16);
|
||||
return imm;
|
||||
}
|
||||
|
||||
/** Construct short immediate register */
|
||||
static INLINE struct brw_reg brw_imm_w( GLshort w )
|
||||
{
|
||||
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
|
||||
imm.dw1.d = w | (w << 16);
|
||||
return imm;
|
||||
}
|
||||
|
||||
/* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
|
||||
* numbers alias with _V and _VF below:
|
||||
*/
|
||||
|
||||
/** Construct vector of eight signed half-byte values */
|
||||
static INLINE struct brw_reg brw_imm_v( GLuint v )
|
||||
{
|
||||
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V);
|
||||
imm.vstride = BRW_VERTICAL_STRIDE_0;
|
||||
imm.width = BRW_WIDTH_8;
|
||||
imm.hstride = BRW_HORIZONTAL_STRIDE_1;
|
||||
imm.dw1.ud = v;
|
||||
return imm;
|
||||
}
|
||||
|
||||
/** Construct vector of four 8-bit float values */
|
||||
static INLINE struct brw_reg brw_imm_vf( GLuint v )
|
||||
{
|
||||
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
|
||||
imm.vstride = BRW_VERTICAL_STRIDE_0;
|
||||
imm.width = BRW_WIDTH_4;
|
||||
imm.hstride = BRW_HORIZONTAL_STRIDE_1;
|
||||
imm.dw1.ud = v;
|
||||
return imm;
|
||||
}
|
||||
|
||||
#define VF_ZERO 0x0
|
||||
#define VF_ONE 0x30
|
||||
#define VF_NEG (1<<7)
|
||||
|
||||
static INLINE struct brw_reg brw_imm_vf4( GLuint v0,
|
||||
GLuint v1,
|
||||
GLuint v2,
|
||||
GLuint v3)
|
||||
{
|
||||
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
|
||||
imm.vstride = BRW_VERTICAL_STRIDE_0;
|
||||
imm.width = BRW_WIDTH_4;
|
||||
imm.hstride = BRW_HORIZONTAL_STRIDE_1;
|
||||
imm.dw1.ud = ((v0 << 0) |
|
||||
(v1 << 8) |
|
||||
(v2 << 16) |
|
||||
(v3 << 24));
|
||||
return imm;
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct brw_reg brw_address( struct brw_reg reg )
|
||||
{
|
||||
return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr);
|
||||
}
|
||||
|
||||
/** Construct float[1] general-purpose register */
|
||||
static INLINE struct brw_reg brw_vec1_grf( GLuint nr, GLuint subnr )
|
||||
{
|
||||
return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
||||
}
|
||||
|
||||
/** Construct float[2] general-purpose register */
|
||||
static INLINE struct brw_reg brw_vec2_grf( GLuint nr, GLuint subnr )
|
||||
{
|
||||
return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
||||
}
|
||||
|
||||
/** Construct float[4] general-purpose register */
|
||||
static INLINE struct brw_reg brw_vec4_grf( GLuint nr, GLuint subnr )
|
||||
{
|
||||
return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
||||
}
|
||||
|
||||
/** Construct float[8] general-purpose register */
|
||||
static INLINE struct brw_reg brw_vec8_grf( GLuint nr, GLuint subnr )
|
||||
{
|
||||
return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct brw_reg brw_uw8_grf( GLuint nr, GLuint subnr )
|
||||
{
|
||||
return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg brw_uw16_grf( GLuint nr, GLuint subnr )
|
||||
{
|
||||
return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
||||
}
|
||||
|
||||
|
||||
/** Construct null register (usually used for setting condition codes) */
|
||||
static INLINE struct brw_reg brw_null_reg( void )
|
||||
{
|
||||
return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
||||
BRW_ARF_NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg brw_address_reg( GLuint subnr )
|
||||
{
|
||||
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
||||
BRW_ARF_ADDRESS,
|
||||
subnr);
|
||||
}
|
||||
|
||||
/* If/else instructions break in align16 mode if writemask & swizzle
|
||||
* aren't xyzw. This goes against the convention for other scalar
|
||||
* regs:
|
||||
*/
|
||||
static INLINE struct brw_reg brw_ip_reg( void )
|
||||
{
|
||||
return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
||||
BRW_ARF_IP,
|
||||
0,
|
||||
BRW_REGISTER_TYPE_UD,
|
||||
BRW_VERTICAL_STRIDE_4, /* ? */
|
||||
BRW_WIDTH_1,
|
||||
BRW_HORIZONTAL_STRIDE_0,
|
||||
BRW_SWIZZLE_XYZW, /* NOTE! */
|
||||
BRW_WRITEMASK_XYZW); /* NOTE! */
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg brw_acc_reg( void )
|
||||
{
|
||||
return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
||||
BRW_ARF_ACCUMULATOR,
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct brw_reg brw_flag_reg( void )
|
||||
{
|
||||
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
||||
BRW_ARF_FLAG,
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct brw_reg brw_mask_reg( GLuint subnr )
|
||||
{
|
||||
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
||||
BRW_ARF_MASK,
|
||||
subnr);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg brw_message_reg( GLuint nr )
|
||||
{
|
||||
assert(nr < BRW_MAX_MRF);
|
||||
return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE,
|
||||
nr,
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* This is almost always called with a numeric constant argument, so
|
||||
* make things easy to evaluate at compile time:
|
||||
*/
|
||||
static INLINE GLuint cvt( GLuint val )
|
||||
{
|
||||
switch (val) {
|
||||
case 0: return 0;
|
||||
case 1: return 1;
|
||||
case 2: return 2;
|
||||
case 4: return 3;
|
||||
case 8: return 4;
|
||||
case 16: return 5;
|
||||
case 32: return 6;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg stride( struct brw_reg reg,
|
||||
GLuint vstride,
|
||||
GLuint width,
|
||||
GLuint hstride )
|
||||
{
|
||||
reg.vstride = cvt(vstride);
|
||||
reg.width = cvt(width) - 1;
|
||||
reg.hstride = cvt(hstride);
|
||||
return reg;
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct brw_reg vec16( struct brw_reg reg )
|
||||
{
|
||||
return stride(reg, 16,16,1);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg vec8( struct brw_reg reg )
|
||||
{
|
||||
return stride(reg, 8,8,1);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg vec4( struct brw_reg reg )
|
||||
{
|
||||
return stride(reg, 4,4,1);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg vec2( struct brw_reg reg )
|
||||
{
|
||||
return stride(reg, 2,2,1);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg vec1( struct brw_reg reg )
|
||||
{
|
||||
return stride(reg, 0,1,0);
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct brw_reg get_element( struct brw_reg reg, GLuint elt )
|
||||
{
|
||||
return vec1(suboffset(reg, elt));
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg get_element_ud( struct brw_reg reg, GLuint elt )
|
||||
{
|
||||
return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_UD), elt));
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct brw_reg brw_swizzle( struct brw_reg reg,
|
||||
GLuint x,
|
||||
GLuint y,
|
||||
GLuint z,
|
||||
GLuint w)
|
||||
{
|
||||
reg.dw1.bits.swizzle = BRW_SWIZZLE4(BRW_GET_SWZ(reg.dw1.bits.swizzle, x),
|
||||
BRW_GET_SWZ(reg.dw1.bits.swizzle, y),
|
||||
BRW_GET_SWZ(reg.dw1.bits.swizzle, z),
|
||||
BRW_GET_SWZ(reg.dw1.bits.swizzle, w));
|
||||
return reg;
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct brw_reg brw_swizzle1( struct brw_reg reg,
|
||||
GLuint x )
|
||||
{
|
||||
return brw_swizzle(reg, x, x, x, x);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg brw_writemask( struct brw_reg reg,
|
||||
GLuint mask )
|
||||
{
|
||||
reg.dw1.bits.writemask &= mask;
|
||||
return reg;
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg brw_set_writemask( struct brw_reg reg,
|
||||
GLuint mask )
|
||||
{
|
||||
reg.dw1.bits.writemask = mask;
|
||||
return reg;
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg negate( struct brw_reg reg )
|
||||
{
|
||||
reg.negate ^= 1;
|
||||
return reg;
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg brw_abs( struct brw_reg reg )
|
||||
{
|
||||
reg.abs = 1;
|
||||
return reg;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*/
|
||||
static INLINE struct brw_reg brw_vec4_indirect( GLuint subnr,
|
||||
GLint offset )
|
||||
{
|
||||
struct brw_reg reg = brw_vec4_grf(0, 0);
|
||||
reg.subnr = subnr;
|
||||
reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
|
||||
reg.dw1.bits.indirect_offset = offset;
|
||||
return reg;
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg brw_vec1_indirect( GLuint subnr,
|
||||
GLint offset )
|
||||
{
|
||||
struct brw_reg reg = brw_vec1_grf(0, 0);
|
||||
reg.subnr = subnr;
|
||||
reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
|
||||
reg.dw1.bits.indirect_offset = offset;
|
||||
return reg;
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg deref_4f(struct brw_indirect ptr, GLint offset)
|
||||
{
|
||||
return brw_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg deref_1f(struct brw_indirect ptr, GLint offset)
|
||||
{
|
||||
return brw_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg deref_4b(struct brw_indirect ptr, GLint offset)
|
||||
{
|
||||
return retype(deref_4f(ptr, offset), BRW_REGISTER_TYPE_B);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg deref_1uw(struct brw_indirect ptr, GLint offset)
|
||||
{
|
||||
return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UW);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg deref_1d(struct brw_indirect ptr, GLint offset)
|
||||
{
|
||||
return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_D);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg deref_1ud(struct brw_indirect ptr, GLint offset)
|
||||
{
|
||||
return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UD);
|
||||
}
|
||||
|
||||
static INLINE struct brw_reg get_addr_reg(struct brw_indirect ptr)
|
||||
{
|
||||
return brw_address_reg(ptr.addr_subnr);
|
||||
}
|
||||
|
||||
static INLINE struct brw_indirect brw_indirect_offset( struct brw_indirect ptr, GLint offset )
|
||||
{
|
||||
ptr.addr_offset += offset;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static INLINE struct brw_indirect brw_indirect( GLuint addr_subnr, GLint offset )
|
||||
{
|
||||
struct brw_indirect ptr;
|
||||
ptr.addr_subnr = addr_subnr;
|
||||
ptr.addr_offset = offset;
|
||||
ptr.pad = 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/** Do two brw_regs refer to the same register? */
|
||||
static INLINE GLboolean
|
||||
brw_same_reg(struct brw_reg r1, struct brw_reg r2)
|
||||
{
|
||||
return r1.file == r2.file && r1.nr == r2.nr;
|
||||
}
|
||||
|
||||
static INLINE struct brw_instruction *current_insn( struct brw_compile *p)
|
||||
{
|
||||
return &p->store[p->nr_insn];
|
||||
}
|
||||
|
||||
void brw_pop_insn_state( struct brw_compile *p );
|
||||
void brw_push_insn_state( struct brw_compile *p );
|
||||
void brw_set_mask_control( struct brw_compile *p, GLuint value );
|
||||
void brw_set_saturate( struct brw_compile *p, GLuint value );
|
||||
void brw_set_access_mode( struct brw_compile *p, GLuint access_mode );
|
||||
void brw_set_compression_control( struct brw_compile *p, GLboolean control );
|
||||
void brw_set_predicate_control_flag_value( struct brw_compile *p, GLuint value );
|
||||
void brw_set_predicate_control( struct brw_compile *p, GLuint pc );
|
||||
void brw_set_conditionalmod( struct brw_compile *p, GLuint conditional );
|
||||
|
||||
void brw_init_compile( struct brw_context *, struct brw_compile *p );
|
||||
|
||||
enum pipe_error brw_get_program( struct brw_compile *p,
|
||||
const GLuint **program,
|
||||
GLuint *sz );
|
||||
|
||||
|
||||
/* Helpers for regular instructions:
|
||||
*/
|
||||
#define ALU1(OP) \
|
||||
struct brw_instruction *brw_##OP(struct brw_compile *p, \
|
||||
struct brw_reg dest, \
|
||||
struct brw_reg src0);
|
||||
|
||||
#define ALU2(OP) \
|
||||
struct brw_instruction *brw_##OP(struct brw_compile *p, \
|
||||
struct brw_reg dest, \
|
||||
struct brw_reg src0, \
|
||||
struct brw_reg src1);
|
||||
|
||||
ALU1(MOV)
|
||||
ALU2(SEL)
|
||||
ALU1(NOT)
|
||||
ALU2(AND)
|
||||
ALU2(OR)
|
||||
ALU2(XOR)
|
||||
ALU2(SHR)
|
||||
ALU2(SHL)
|
||||
ALU2(RSR)
|
||||
ALU2(RSL)
|
||||
ALU2(ASR)
|
||||
ALU2(JMPI)
|
||||
ALU2(ADD)
|
||||
ALU2(MUL)
|
||||
ALU1(FRC)
|
||||
ALU1(RNDD)
|
||||
ALU1(RNDZ)
|
||||
ALU2(MAC)
|
||||
ALU2(MACH)
|
||||
ALU1(LZD)
|
||||
ALU2(DP4)
|
||||
ALU2(DPH)
|
||||
ALU2(DP3)
|
||||
ALU2(DP2)
|
||||
ALU2(LINE)
|
||||
|
||||
#undef ALU1
|
||||
#undef ALU2
|
||||
|
||||
|
||||
|
||||
/* Helpers for SEND instruction:
|
||||
*/
|
||||
void brw_urb_WRITE(struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
GLuint msg_reg_nr,
|
||||
struct brw_reg src0,
|
||||
GLboolean allocate,
|
||||
GLboolean used,
|
||||
GLuint msg_length,
|
||||
GLuint response_length,
|
||||
GLboolean eot,
|
||||
GLboolean writes_complete,
|
||||
GLuint offset,
|
||||
GLuint swizzle);
|
||||
|
||||
void brw_ff_sync(struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
GLuint msg_reg_nr,
|
||||
struct brw_reg src0,
|
||||
GLboolean allocate,
|
||||
GLboolean used,
|
||||
GLuint msg_length,
|
||||
GLuint response_length,
|
||||
GLboolean eot,
|
||||
GLboolean writes_complete,
|
||||
GLuint offset,
|
||||
GLuint swizzle);
|
||||
|
||||
void brw_fb_WRITE(struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
GLuint msg_reg_nr,
|
||||
struct brw_reg src0,
|
||||
GLuint binding_table_index,
|
||||
GLuint msg_length,
|
||||
GLuint response_length,
|
||||
GLboolean eot);
|
||||
|
||||
void brw_SAMPLE(struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
GLuint msg_reg_nr,
|
||||
struct brw_reg src0,
|
||||
GLuint binding_table_index,
|
||||
GLuint sampler,
|
||||
GLuint writemask,
|
||||
GLuint msg_type,
|
||||
GLuint response_length,
|
||||
GLuint msg_length,
|
||||
GLboolean eot,
|
||||
GLuint header_present,
|
||||
GLuint simd_mode);
|
||||
|
||||
void brw_math_16( struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
GLuint function,
|
||||
GLuint saturate,
|
||||
GLuint msg_reg_nr,
|
||||
struct brw_reg src,
|
||||
GLuint precision );
|
||||
|
||||
void brw_math( struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
GLuint function,
|
||||
GLuint saturate,
|
||||
GLuint msg_reg_nr,
|
||||
struct brw_reg src,
|
||||
GLuint data_type,
|
||||
GLuint precision );
|
||||
|
||||
void brw_dp_READ_16( struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
GLuint scratch_offset );
|
||||
|
||||
void brw_dp_READ_4( struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
GLboolean relAddr,
|
||||
GLuint location,
|
||||
GLuint bind_table_index );
|
||||
|
||||
void brw_dp_READ_4_vs( struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
GLuint oword,
|
||||
GLboolean relAddr,
|
||||
struct brw_reg addrReg,
|
||||
GLuint location,
|
||||
GLuint bind_table_index );
|
||||
|
||||
void brw_dp_WRITE_16( struct brw_compile *p,
|
||||
struct brw_reg src,
|
||||
GLuint scratch_offset );
|
||||
|
||||
/* If/else/endif. Works by manipulating the execution flags on each
|
||||
* channel.
|
||||
*/
|
||||
struct brw_instruction *brw_IF(struct brw_compile *p,
|
||||
GLuint execute_size);
|
||||
|
||||
struct brw_instruction *brw_ELSE(struct brw_compile *p,
|
||||
struct brw_instruction *if_insn);
|
||||
|
||||
void brw_ENDIF(struct brw_compile *p,
|
||||
struct brw_instruction *if_or_else_insn);
|
||||
|
||||
|
||||
/* DO/WHILE loops:
|
||||
*/
|
||||
struct brw_instruction *brw_DO(struct brw_compile *p,
|
||||
GLuint execute_size);
|
||||
|
||||
struct brw_instruction *brw_WHILE(struct brw_compile *p,
|
||||
struct brw_instruction *patch_insn);
|
||||
|
||||
struct brw_instruction *brw_BREAK(struct brw_compile *p);
|
||||
struct brw_instruction *brw_CONT(struct brw_compile *p);
|
||||
/* Forward jumps:
|
||||
*/
|
||||
void brw_land_fwd_jump(struct brw_compile *p,
|
||||
struct brw_instruction *jmp_insn);
|
||||
|
||||
|
||||
|
||||
void brw_NOP(struct brw_compile *p);
|
||||
|
||||
/* Special case: there is never a destination, execution size will be
|
||||
* taken from src0:
|
||||
*/
|
||||
void brw_CMP(struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
GLuint conditional,
|
||||
struct brw_reg src0,
|
||||
struct brw_reg src1);
|
||||
|
||||
void brw_print_reg( struct brw_reg reg );
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* brw_eu_util.c:
|
||||
*/
|
||||
|
||||
void brw_copy_indirect_to_indirect(struct brw_compile *p,
|
||||
struct brw_indirect dst_ptr,
|
||||
struct brw_indirect src_ptr,
|
||||
GLuint count);
|
||||
|
||||
void brw_copy_from_indirect(struct brw_compile *p,
|
||||
struct brw_reg dst,
|
||||
struct brw_indirect ptr,
|
||||
GLuint count);
|
||||
|
||||
void brw_copy4(struct brw_compile *p,
|
||||
struct brw_reg dst,
|
||||
struct brw_reg src,
|
||||
GLuint count);
|
||||
|
||||
void brw_copy8(struct brw_compile *p,
|
||||
struct brw_reg dst,
|
||||
struct brw_reg src,
|
||||
GLuint count);
|
||||
|
||||
void brw_math_invert( struct brw_compile *p,
|
||||
struct brw_reg dst,
|
||||
struct brw_reg src);
|
||||
|
||||
void brw_set_src1( struct brw_instruction *insn,
|
||||
struct brw_reg reg );
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_debug.h"
|
||||
|
||||
#include "brw_eu.h"
|
||||
|
||||
void brw_print_reg( struct brw_reg hwreg )
|
||||
{
|
||||
static const char *file[] = {
|
||||
"arf",
|
||||
"grf",
|
||||
"msg",
|
||||
"imm"
|
||||
};
|
||||
|
||||
static const char *type[] = {
|
||||
"ud",
|
||||
"d",
|
||||
"uw",
|
||||
"w",
|
||||
"ub",
|
||||
"vf",
|
||||
"hf",
|
||||
"f"
|
||||
};
|
||||
|
||||
debug_printf("%s%s",
|
||||
hwreg.abs ? "abs/" : "",
|
||||
hwreg.negate ? "-" : "");
|
||||
|
||||
if (hwreg.file == BRW_GENERAL_REGISTER_FILE &&
|
||||
hwreg.nr % 2 == 0 &&
|
||||
hwreg.subnr == 0 &&
|
||||
hwreg.vstride == BRW_VERTICAL_STRIDE_8 &&
|
||||
hwreg.width == BRW_WIDTH_8 &&
|
||||
hwreg.hstride == BRW_HORIZONTAL_STRIDE_1 &&
|
||||
hwreg.type == BRW_REGISTER_TYPE_F) {
|
||||
/* vector register */
|
||||
debug_printf("vec%d", hwreg.nr);
|
||||
}
|
||||
else if (hwreg.file == BRW_GENERAL_REGISTER_FILE &&
|
||||
hwreg.vstride == BRW_VERTICAL_STRIDE_0 &&
|
||||
hwreg.width == BRW_WIDTH_1 &&
|
||||
hwreg.hstride == BRW_HORIZONTAL_STRIDE_0 &&
|
||||
hwreg.type == BRW_REGISTER_TYPE_F) {
|
||||
/* "scalar" register */
|
||||
debug_printf("scl%d.%d", hwreg.nr, hwreg.subnr / 4);
|
||||
}
|
||||
else if (hwreg.file == BRW_IMMEDIATE_VALUE) {
|
||||
debug_printf("imm %f", hwreg.dw1.f);
|
||||
}
|
||||
else {
|
||||
debug_printf("%s%d.%d<%d;%d,%d>:%s",
|
||||
file[hwreg.file],
|
||||
hwreg.nr,
|
||||
hwreg.subnr / type_sz(hwreg.type),
|
||||
hwreg.vstride ? (1<<(hwreg.vstride-1)) : 0,
|
||||
1<<hwreg.width,
|
||||
hwreg.hstride ? (1<<(hwreg.hstride-1)) : 0,
|
||||
type[hwreg.type]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_eu.h"
|
||||
|
||||
|
||||
void brw_math_invert( struct brw_compile *p,
|
||||
struct brw_reg dst,
|
||||
struct brw_reg src)
|
||||
{
|
||||
brw_math( p,
|
||||
dst,
|
||||
BRW_MATH_FUNCTION_INV,
|
||||
BRW_MATH_SATURATE_NONE,
|
||||
0,
|
||||
src,
|
||||
BRW_MATH_PRECISION_FULL,
|
||||
BRW_MATH_DATA_VECTOR );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void brw_copy4(struct brw_compile *p,
|
||||
struct brw_reg dst,
|
||||
struct brw_reg src,
|
||||
GLuint count)
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
dst = vec4(dst);
|
||||
src = vec4(src);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
GLuint delta = i*32;
|
||||
brw_MOV(p, byte_offset(dst, delta), byte_offset(src, delta));
|
||||
brw_MOV(p, byte_offset(dst, delta+16), byte_offset(src, delta+16));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void brw_copy8(struct brw_compile *p,
|
||||
struct brw_reg dst,
|
||||
struct brw_reg src,
|
||||
GLuint count)
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
dst = vec8(dst);
|
||||
src = vec8(src);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
GLuint delta = i*32;
|
||||
brw_MOV(p, byte_offset(dst, delta), byte_offset(src, delta));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void brw_copy_indirect_to_indirect(struct brw_compile *p,
|
||||
struct brw_indirect dst_ptr,
|
||||
struct brw_indirect src_ptr,
|
||||
GLuint count)
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
GLuint delta = i*32;
|
||||
brw_MOV(p, deref_4f(dst_ptr, delta), deref_4f(src_ptr, delta));
|
||||
brw_MOV(p, deref_4f(dst_ptr, delta+16), deref_4f(src_ptr, delta+16));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void brw_copy_from_indirect(struct brw_compile *p,
|
||||
struct brw_reg dst,
|
||||
struct brw_indirect ptr,
|
||||
GLuint count)
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
dst = vec4(dst);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
GLuint delta = i*32;
|
||||
brw_MOV(p, byte_offset(dst, delta), deref_4f(ptr, delta));
|
||||
brw_MOV(p, byte_offset(dst, delta+16), deref_4f(ptr, delta+16));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "brw_batchbuffer.h"
|
||||
|
||||
#include "brw_defines.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_eu.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_gs.h"
|
||||
|
||||
|
||||
|
||||
static enum pipe_error compile_gs_prog( struct brw_context *brw,
|
||||
struct brw_gs_prog_key *key,
|
||||
struct brw_winsys_buffer **bo_out )
|
||||
{
|
||||
struct brw_gs_compile c;
|
||||
enum pipe_error ret;
|
||||
const GLuint *program;
|
||||
GLuint program_size;
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
c.key = *key;
|
||||
c.need_ff_sync = BRW_IS_IGDNG(brw);
|
||||
/* Need to locate the two positions present in vertex + header.
|
||||
* These are currently hardcoded:
|
||||
*/
|
||||
c.nr_attrs = c.key.nr_attrs;
|
||||
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
c.nr_regs = (c.nr_attrs + 1) / 2 + 3; /* are vertices packed, or reg-aligned? */
|
||||
else
|
||||
c.nr_regs = (c.nr_attrs + 1) / 2 + 1; /* are vertices packed, or reg-aligned? */
|
||||
|
||||
c.nr_bytes = c.nr_regs * REG_SIZE;
|
||||
|
||||
|
||||
/* Begin the compilation:
|
||||
*/
|
||||
brw_init_compile(brw, &c.func);
|
||||
|
||||
c.func.single_program_flow = 1;
|
||||
|
||||
/* For some reason the thread is spawned with only 4 channels
|
||||
* unmasked.
|
||||
*/
|
||||
brw_set_mask_control(&c.func, BRW_MASK_DISABLE);
|
||||
|
||||
|
||||
/* Note that primitives which don't require a GS program have
|
||||
* already been weeded out by this stage:
|
||||
*/
|
||||
switch (key->primitive) {
|
||||
case PIPE_PRIM_QUADS:
|
||||
brw_gs_quads( &c );
|
||||
break;
|
||||
case PIPE_PRIM_QUAD_STRIP:
|
||||
brw_gs_quad_strip( &c );
|
||||
break;
|
||||
case PIPE_PRIM_LINE_LOOP:
|
||||
brw_gs_lines( &c );
|
||||
break;
|
||||
case PIPE_PRIM_LINES:
|
||||
if (key->hint_gs_always)
|
||||
brw_gs_lines( &c );
|
||||
else {
|
||||
return PIPE_OK;
|
||||
}
|
||||
break;
|
||||
case PIPE_PRIM_TRIANGLES:
|
||||
if (key->hint_gs_always)
|
||||
brw_gs_tris( &c );
|
||||
else {
|
||||
return PIPE_OK;
|
||||
}
|
||||
break;
|
||||
case PIPE_PRIM_POINTS:
|
||||
if (key->hint_gs_always)
|
||||
brw_gs_points( &c );
|
||||
else {
|
||||
return PIPE_OK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return PIPE_ERROR_BAD_INPUT;
|
||||
}
|
||||
|
||||
/* get the program
|
||||
*/
|
||||
ret = brw_get_program(&c.func, &program, &program_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Upload
|
||||
*/
|
||||
ret = brw_upload_cache( &brw->cache, BRW_GS_PROG,
|
||||
&c.key, sizeof(c.key),
|
||||
NULL, 0,
|
||||
program, program_size,
|
||||
&c.prog_data,
|
||||
&brw->gs.prog_data,
|
||||
bo_out );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
static const unsigned gs_prim[PIPE_PRIM_MAX] = {
|
||||
PIPE_PRIM_POINTS,
|
||||
PIPE_PRIM_LINES,
|
||||
PIPE_PRIM_LINE_LOOP,
|
||||
PIPE_PRIM_LINES,
|
||||
PIPE_PRIM_TRIANGLES,
|
||||
PIPE_PRIM_TRIANGLES,
|
||||
PIPE_PRIM_TRIANGLES,
|
||||
PIPE_PRIM_QUADS,
|
||||
PIPE_PRIM_QUAD_STRIP,
|
||||
PIPE_PRIM_TRIANGLES
|
||||
};
|
||||
|
||||
static void populate_key( struct brw_context *brw,
|
||||
struct brw_gs_prog_key *key )
|
||||
{
|
||||
const struct brw_fs_signature *sig = &brw->curr.fragment_shader->signature;
|
||||
|
||||
memset(key, 0, sizeof(*key));
|
||||
|
||||
/* PIPE_NEW_FRAGMENT_SIGNATURE */
|
||||
key->nr_attrs = sig->nr_inputs + 1;
|
||||
|
||||
/* BRW_NEW_PRIMITIVE */
|
||||
key->primitive = gs_prim[brw->primitive];
|
||||
|
||||
key->hint_gs_always = 0; /* debug code? */
|
||||
|
||||
key->need_gs_prog = (key->hint_gs_always ||
|
||||
brw->primitive == PIPE_PRIM_QUADS ||
|
||||
brw->primitive == PIPE_PRIM_QUAD_STRIP ||
|
||||
brw->primitive == PIPE_PRIM_LINE_LOOP);
|
||||
}
|
||||
|
||||
/* Calculate interpolants for triangle and line rasterization.
|
||||
*/
|
||||
static int prepare_gs_prog(struct brw_context *brw)
|
||||
{
|
||||
struct brw_gs_prog_key key;
|
||||
enum pipe_error ret;
|
||||
|
||||
/* Populate the key:
|
||||
*/
|
||||
populate_key(brw, &key);
|
||||
|
||||
if (brw->gs.prog_active != key.need_gs_prog) {
|
||||
brw->state.dirty.cache |= CACHE_NEW_GS_PROG;
|
||||
brw->gs.prog_active = key.need_gs_prog;
|
||||
}
|
||||
|
||||
if (!brw->gs.prog_active)
|
||||
return PIPE_OK;
|
||||
|
||||
if (brw_search_cache(&brw->cache, BRW_GS_PROG,
|
||||
&key, sizeof(key),
|
||||
NULL, 0,
|
||||
&brw->gs.prog_data,
|
||||
&brw->gs.prog_bo))
|
||||
return PIPE_OK;
|
||||
|
||||
ret = compile_gs_prog( brw, &key, &brw->gs.prog_bo );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
const struct brw_tracked_state brw_gs_prog = {
|
||||
.dirty = {
|
||||
.mesa = PIPE_NEW_FRAGMENT_SIGNATURE,
|
||||
.brw = BRW_NEW_PRIMITIVE,
|
||||
.cache = 0,
|
||||
},
|
||||
.prepare = prepare_gs_prog
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BRW_GS_H
|
||||
#define BRW_GS_H
|
||||
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_eu.h"
|
||||
|
||||
#define MAX_GS_VERTS (4)
|
||||
|
||||
struct brw_gs_prog_key {
|
||||
GLuint nr_attrs:8;
|
||||
GLuint primitive:4;
|
||||
GLuint hint_gs_always:1;
|
||||
GLuint need_gs_prog:1;
|
||||
GLuint pad:18;
|
||||
};
|
||||
|
||||
struct brw_gs_compile {
|
||||
struct brw_compile func;
|
||||
struct brw_gs_prog_key key;
|
||||
struct brw_gs_prog_data prog_data;
|
||||
|
||||
struct {
|
||||
struct brw_reg R0;
|
||||
struct brw_reg vertex[MAX_GS_VERTS];
|
||||
} reg;
|
||||
|
||||
/* 3 different ways of expressing vertex size:
|
||||
*/
|
||||
GLuint nr_attrs;
|
||||
GLuint nr_regs;
|
||||
GLuint nr_bytes;
|
||||
GLboolean need_ff_sync;
|
||||
};
|
||||
|
||||
#define ATTR_SIZE (4*4)
|
||||
|
||||
void brw_gs_quads( struct brw_gs_compile *c );
|
||||
void brw_gs_quad_strip( struct brw_gs_compile *c );
|
||||
void brw_gs_tris( struct brw_gs_compile *c );
|
||||
void brw_gs_lines( struct brw_gs_compile *c );
|
||||
void brw_gs_points( struct brw_gs_compile *c );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "brw_batchbuffer.h"
|
||||
|
||||
#include "brw_defines.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_eu.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_gs.h"
|
||||
|
||||
static void brw_gs_alloc_regs( struct brw_gs_compile *c,
|
||||
GLuint nr_verts )
|
||||
{
|
||||
GLuint i = 0,j;
|
||||
|
||||
/* Register usage is static, precompute here:
|
||||
*/
|
||||
c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
|
||||
|
||||
/* Payload vertices plus space for more generated vertices:
|
||||
*/
|
||||
for (j = 0; j < nr_verts; j++) {
|
||||
c->reg.vertex[j] = brw_vec4_grf(i, 0);
|
||||
i += c->nr_regs;
|
||||
}
|
||||
|
||||
c->prog_data.urb_read_length = c->nr_regs;
|
||||
c->prog_data.total_grf = i;
|
||||
}
|
||||
|
||||
|
||||
static void brw_gs_emit_vue(struct brw_gs_compile *c,
|
||||
struct brw_reg vert,
|
||||
GLboolean last,
|
||||
GLuint header)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
GLboolean allocate = !last;
|
||||
|
||||
/* Overwrite PrimType and PrimStart in the message header, for
|
||||
* each vertex in turn:
|
||||
*/
|
||||
brw_MOV(p, get_element_ud(c->reg.R0, 2), brw_imm_ud(header));
|
||||
|
||||
/* Copy the vertex from vertn into m1..mN+1:
|
||||
*/
|
||||
brw_copy8(p, brw_message_reg(1), vert, c->nr_regs);
|
||||
|
||||
/* Send each vertex as a seperate write to the urb. This is
|
||||
* different to the concept in brw_sf_emit.c, where subsequent
|
||||
* writes are used to build up a single urb entry. Each of these
|
||||
* writes instantiates a seperate urb entry, and a new one must be
|
||||
* allocated each time.
|
||||
*/
|
||||
brw_urb_WRITE(p,
|
||||
allocate ? c->reg.R0 : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
|
||||
0,
|
||||
c->reg.R0,
|
||||
allocate,
|
||||
1, /* used */
|
||||
c->nr_regs + 1, /* msg length */
|
||||
allocate ? 1 : 0, /* response length */
|
||||
allocate ? 0 : 1, /* eot */
|
||||
1, /* writes_complete */
|
||||
0, /* urb offset */
|
||||
BRW_URB_SWIZZLE_NONE);
|
||||
}
|
||||
|
||||
static void brw_gs_ff_sync(struct brw_gs_compile *c, int num_prim)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
brw_MOV(p, get_element_ud(c->reg.R0, 1), brw_imm_ud(num_prim));
|
||||
brw_ff_sync(p,
|
||||
c->reg.R0,
|
||||
0,
|
||||
c->reg.R0,
|
||||
1,
|
||||
1, /* used */
|
||||
1, /* msg length */
|
||||
1, /* response length */
|
||||
0, /* eot */
|
||||
1, /* write compelete */
|
||||
0, /* urb offset */
|
||||
BRW_URB_SWIZZLE_NONE);
|
||||
}
|
||||
|
||||
|
||||
void brw_gs_quads( struct brw_gs_compile *c )
|
||||
{
|
||||
brw_gs_alloc_regs(c, 4);
|
||||
|
||||
/* Use polygons for correct edgeflag behaviour. Note that vertex 3
|
||||
* is the PV for quads, but vertex 0 for polygons:
|
||||
*/
|
||||
if (c->need_ff_sync)
|
||||
brw_gs_ff_sync(c, 1);
|
||||
brw_gs_emit_vue(c, c->reg.vertex[3], 0, ((_3DPRIM_POLYGON << 2) | R02_PRIM_START));
|
||||
brw_gs_emit_vue(c, c->reg.vertex[0], 0, (_3DPRIM_POLYGON << 2));
|
||||
brw_gs_emit_vue(c, c->reg.vertex[1], 0, (_3DPRIM_POLYGON << 2));
|
||||
brw_gs_emit_vue(c, c->reg.vertex[2], 1, ((_3DPRIM_POLYGON << 2) | R02_PRIM_END));
|
||||
}
|
||||
|
||||
void brw_gs_quad_strip( struct brw_gs_compile *c )
|
||||
{
|
||||
brw_gs_alloc_regs(c, 4);
|
||||
|
||||
if (c->need_ff_sync)
|
||||
brw_gs_ff_sync(c, 1);
|
||||
brw_gs_emit_vue(c, c->reg.vertex[2], 0, ((_3DPRIM_POLYGON << 2) | R02_PRIM_START));
|
||||
brw_gs_emit_vue(c, c->reg.vertex[3], 0, (_3DPRIM_POLYGON << 2));
|
||||
brw_gs_emit_vue(c, c->reg.vertex[0], 0, (_3DPRIM_POLYGON << 2));
|
||||
brw_gs_emit_vue(c, c->reg.vertex[1], 1, ((_3DPRIM_POLYGON << 2) | R02_PRIM_END));
|
||||
}
|
||||
|
||||
void brw_gs_tris( struct brw_gs_compile *c )
|
||||
{
|
||||
brw_gs_alloc_regs(c, 3);
|
||||
|
||||
if (c->need_ff_sync)
|
||||
brw_gs_ff_sync(c, 1);
|
||||
brw_gs_emit_vue(c, c->reg.vertex[0], 0, ((_3DPRIM_TRILIST << 2) | R02_PRIM_START));
|
||||
brw_gs_emit_vue(c, c->reg.vertex[1], 0, (_3DPRIM_TRILIST << 2));
|
||||
brw_gs_emit_vue(c, c->reg.vertex[2], 1, ((_3DPRIM_TRILIST << 2) | R02_PRIM_END));
|
||||
}
|
||||
|
||||
void brw_gs_lines( struct brw_gs_compile *c )
|
||||
{
|
||||
brw_gs_alloc_regs(c, 2);
|
||||
|
||||
if (c->need_ff_sync)
|
||||
brw_gs_ff_sync(c, 1);
|
||||
brw_gs_emit_vue(c, c->reg.vertex[0], 0, ((_3DPRIM_LINESTRIP << 2) | R02_PRIM_START));
|
||||
brw_gs_emit_vue(c, c->reg.vertex[1], 1, ((_3DPRIM_LINESTRIP << 2) | R02_PRIM_END));
|
||||
}
|
||||
|
||||
void brw_gs_points( struct brw_gs_compile *c )
|
||||
{
|
||||
brw_gs_alloc_regs(c, 1);
|
||||
|
||||
if (c->need_ff_sync)
|
||||
brw_gs_ff_sync(c, 1);
|
||||
brw_gs_emit_vue(c, c->reg.vertex[0], 1, ((_3DPRIM_POINTLIST << 2) | R02_PRIM_START | R02_PRIM_END));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_debug.h"
|
||||
|
||||
struct brw_gs_unit_key {
|
||||
unsigned int total_grf;
|
||||
unsigned int urb_entry_read_length;
|
||||
|
||||
unsigned int curbe_offset;
|
||||
|
||||
unsigned int nr_urb_entries, urb_size;
|
||||
GLboolean prog_active;
|
||||
};
|
||||
|
||||
static void
|
||||
gs_unit_populate_key(struct brw_context *brw, struct brw_gs_unit_key *key)
|
||||
{
|
||||
memset(key, 0, sizeof(*key));
|
||||
|
||||
/* CACHE_NEW_GS_PROG */
|
||||
key->prog_active = brw->gs.prog_active;
|
||||
if (key->prog_active) {
|
||||
key->total_grf = brw->gs.prog_data->total_grf;
|
||||
key->urb_entry_read_length = brw->gs.prog_data->urb_read_length;
|
||||
} else {
|
||||
key->total_grf = 1;
|
||||
key->urb_entry_read_length = 1;
|
||||
}
|
||||
|
||||
/* BRW_NEW_CURBE_OFFSETS */
|
||||
key->curbe_offset = brw->curbe.clip_start;
|
||||
|
||||
/* BRW_NEW_URB_FENCE */
|
||||
key->nr_urb_entries = brw->urb.nr_gs_entries;
|
||||
key->urb_size = brw->urb.vsize;
|
||||
}
|
||||
|
||||
static enum pipe_error
|
||||
gs_unit_create_from_key(struct brw_context *brw,
|
||||
struct brw_gs_unit_key *key,
|
||||
struct brw_winsys_reloc *reloc,
|
||||
unsigned nr_reloc,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
struct brw_gs_unit_state gs;
|
||||
enum pipe_error ret;
|
||||
|
||||
|
||||
memset(&gs, 0, sizeof(gs));
|
||||
|
||||
/* reloc */
|
||||
gs.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
|
||||
gs.thread0.kernel_start_pointer = 0;
|
||||
|
||||
gs.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
|
||||
gs.thread1.single_program_flow = 1;
|
||||
|
||||
gs.thread3.dispatch_grf_start_reg = 1;
|
||||
gs.thread3.const_urb_entry_read_offset = 0;
|
||||
gs.thread3.const_urb_entry_read_length = 0;
|
||||
gs.thread3.urb_entry_read_offset = 0;
|
||||
gs.thread3.urb_entry_read_length = key->urb_entry_read_length;
|
||||
|
||||
gs.thread4.nr_urb_entries = key->nr_urb_entries;
|
||||
gs.thread4.urb_entry_allocation_size = key->urb_size - 1;
|
||||
|
||||
if (key->nr_urb_entries >= 8)
|
||||
gs.thread4.max_threads = 1;
|
||||
else
|
||||
gs.thread4.max_threads = 0;
|
||||
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
gs.thread4.rendering_enable = 1;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_STATS)
|
||||
gs.thread4.stats_enable = 1;
|
||||
|
||||
ret = brw_upload_cache(&brw->cache, BRW_GS_UNIT,
|
||||
key, sizeof(*key),
|
||||
reloc, nr_reloc,
|
||||
&gs, sizeof(gs),
|
||||
NULL, NULL,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
static enum pipe_error prepare_gs_unit(struct brw_context *brw)
|
||||
{
|
||||
struct brw_gs_unit_key key;
|
||||
enum pipe_error ret;
|
||||
struct brw_winsys_reloc reloc[1];
|
||||
unsigned nr_reloc = 0;
|
||||
unsigned grf_reg_count;
|
||||
|
||||
gs_unit_populate_key(brw, &key);
|
||||
|
||||
grf_reg_count = (align(key.total_grf, 16) / 16 - 1);
|
||||
|
||||
/* GS program relocation */
|
||||
if (key.prog_active) {
|
||||
make_reloc(&reloc[nr_reloc++],
|
||||
BRW_USAGE_STATE,
|
||||
grf_reg_count << 1,
|
||||
offsetof(struct brw_gs_unit_state, thread0),
|
||||
brw->gs.prog_bo);
|
||||
}
|
||||
|
||||
if (brw_search_cache(&brw->cache, BRW_GS_UNIT,
|
||||
&key, sizeof(key),
|
||||
reloc, nr_reloc,
|
||||
NULL,
|
||||
&brw->gs.state_bo))
|
||||
return PIPE_OK;
|
||||
|
||||
ret = gs_unit_create_from_key(brw, &key,
|
||||
reloc, nr_reloc,
|
||||
&brw->gs.state_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_gs_unit = {
|
||||
.dirty = {
|
||||
.mesa = 0,
|
||||
.brw = (BRW_NEW_CURBE_OFFSETS |
|
||||
BRW_NEW_URB_FENCE),
|
||||
.cache = CACHE_NEW_GS_PROG
|
||||
},
|
||||
.prepare = prepare_gs_unit,
|
||||
};
|
||||
@@ -0,0 +1,513 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "brw_debug.h"
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_screen.h"
|
||||
#include "brw_pipe_rast.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Blend color
|
||||
*/
|
||||
|
||||
static int upload_blend_constant_color(struct brw_context *brw)
|
||||
{
|
||||
BRW_CACHED_BATCH_STRUCT(brw, &brw->curr.bcc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const struct brw_tracked_state brw_blend_constant_color = {
|
||||
.dirty = {
|
||||
.mesa = PIPE_NEW_BLEND_COLOR,
|
||||
.brw = 0,
|
||||
.cache = 0
|
||||
},
|
||||
.emit = upload_blend_constant_color
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* Drawing rectangle - framebuffer dimensions
|
||||
*/
|
||||
static int upload_drawing_rect(struct brw_context *brw)
|
||||
{
|
||||
BEGIN_BATCH(4, NO_LOOP_CLIPRECTS);
|
||||
OUT_BATCH(_3DSTATE_DRAWRECT_INFO_I965);
|
||||
OUT_BATCH(0);
|
||||
OUT_BATCH(((brw->curr.fb.width - 1) & 0xffff) |
|
||||
((brw->curr.fb.height - 1) << 16));
|
||||
OUT_BATCH(0);
|
||||
ADVANCE_BATCH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_drawing_rect = {
|
||||
.dirty = {
|
||||
.mesa = PIPE_NEW_FRAMEBUFFER_DIMENSIONS,
|
||||
.brw = 0,
|
||||
.cache = 0
|
||||
},
|
||||
.emit = upload_drawing_rect
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Binding table pointers
|
||||
*/
|
||||
|
||||
static int prepare_binding_table_pointers(struct brw_context *brw)
|
||||
{
|
||||
brw_add_validated_bo(brw, brw->vs.bind_bo);
|
||||
brw_add_validated_bo(brw, brw->wm.bind_bo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload the binding table pointers, which point each stage's array of surface
|
||||
* state pointers.
|
||||
*
|
||||
* The binding table pointers are relative to the surface state base address,
|
||||
* which is 0.
|
||||
*/
|
||||
static int upload_binding_table_pointers(struct brw_context *brw)
|
||||
{
|
||||
BEGIN_BATCH(6, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH(CMD_BINDING_TABLE_PTRS << 16 | (6 - 2));
|
||||
if (brw->vs.bind_bo != NULL)
|
||||
OUT_RELOC(brw->vs.bind_bo,
|
||||
BRW_USAGE_SAMPLER,
|
||||
0); /* vs */
|
||||
else
|
||||
OUT_BATCH(0);
|
||||
OUT_BATCH(0); /* gs */
|
||||
OUT_BATCH(0); /* clip */
|
||||
OUT_BATCH(0); /* sf */
|
||||
OUT_RELOC(brw->wm.bind_bo,
|
||||
BRW_USAGE_SAMPLER,
|
||||
0); /* wm/ps */
|
||||
ADVANCE_BATCH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_binding_table_pointers = {
|
||||
.dirty = {
|
||||
.mesa = 0,
|
||||
.brw = BRW_NEW_BATCH,
|
||||
.cache = CACHE_NEW_SURF_BIND,
|
||||
},
|
||||
.prepare = prepare_binding_table_pointers,
|
||||
.emit = upload_binding_table_pointers,
|
||||
};
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Upload pointers to the per-stage state.
|
||||
*
|
||||
* The state pointers in this packet are all relative to the general state
|
||||
* base address set by CMD_STATE_BASE_ADDRESS, which is 0.
|
||||
*/
|
||||
static int upload_pipelined_state_pointers(struct brw_context *brw )
|
||||
{
|
||||
BEGIN_BATCH(7, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH(CMD_PIPELINED_STATE_POINTERS << 16 | (7 - 2));
|
||||
OUT_RELOC(brw->vs.state_bo,
|
||||
BRW_USAGE_STATE,
|
||||
0);
|
||||
if (brw->gs.prog_active)
|
||||
OUT_RELOC(brw->gs.state_bo,
|
||||
BRW_USAGE_STATE,
|
||||
1);
|
||||
else
|
||||
OUT_BATCH(0);
|
||||
OUT_RELOC(brw->clip.state_bo,
|
||||
BRW_USAGE_STATE,
|
||||
1);
|
||||
OUT_RELOC(brw->sf.state_bo,
|
||||
BRW_USAGE_STATE,
|
||||
0);
|
||||
OUT_RELOC(brw->wm.state_bo,
|
||||
BRW_USAGE_STATE,
|
||||
0);
|
||||
OUT_RELOC(brw->cc.state_bo,
|
||||
BRW_USAGE_STATE,
|
||||
0);
|
||||
ADVANCE_BATCH();
|
||||
|
||||
brw->state.dirty.brw |= BRW_NEW_PSP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int prepare_psp_urb_cbs(struct brw_context *brw)
|
||||
{
|
||||
brw_add_validated_bo(brw, brw->vs.state_bo);
|
||||
brw_add_validated_bo(brw, brw->gs.state_bo);
|
||||
brw_add_validated_bo(brw, brw->clip.state_bo);
|
||||
brw_add_validated_bo(brw, brw->sf.state_bo);
|
||||
brw_add_validated_bo(brw, brw->wm.state_bo);
|
||||
brw_add_validated_bo(brw, brw->cc.state_bo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upload_psp_urb_cbs(struct brw_context *brw )
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = upload_pipelined_state_pointers(brw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = brw_upload_urb_fence(brw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = brw_upload_cs_urb_state(brw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_psp_urb_cbs = {
|
||||
.dirty = {
|
||||
.mesa = 0,
|
||||
.brw = BRW_NEW_URB_FENCE | BRW_NEW_BATCH,
|
||||
.cache = (CACHE_NEW_VS_UNIT |
|
||||
CACHE_NEW_GS_UNIT |
|
||||
CACHE_NEW_GS_PROG |
|
||||
CACHE_NEW_CLIP_UNIT |
|
||||
CACHE_NEW_SF_UNIT |
|
||||
CACHE_NEW_WM_UNIT |
|
||||
CACHE_NEW_CC_UNIT)
|
||||
},
|
||||
.prepare = prepare_psp_urb_cbs,
|
||||
.emit = upload_psp_urb_cbs,
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Depth buffer
|
||||
*/
|
||||
|
||||
static int prepare_depthbuffer(struct brw_context *brw)
|
||||
{
|
||||
struct pipe_surface *zsbuf = brw->curr.fb.zsbuf;
|
||||
|
||||
if (zsbuf)
|
||||
brw_add_validated_bo(brw, brw_surface(zsbuf)->bo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emit_depthbuffer(struct brw_context *brw)
|
||||
{
|
||||
struct pipe_surface *surface = brw->curr.fb.zsbuf;
|
||||
unsigned int len = (BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw)) ? 6 : 5;
|
||||
|
||||
if (surface == NULL) {
|
||||
BEGIN_BATCH(len, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH(CMD_DEPTH_BUFFER << 16 | (len - 2));
|
||||
OUT_BATCH((BRW_DEPTHFORMAT_D32_FLOAT << 18) |
|
||||
(BRW_SURFACE_NULL << 29));
|
||||
OUT_BATCH(0);
|
||||
OUT_BATCH(0);
|
||||
OUT_BATCH(0);
|
||||
|
||||
if (BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw))
|
||||
OUT_BATCH(0);
|
||||
|
||||
ADVANCE_BATCH();
|
||||
} else {
|
||||
struct brw_winsys_buffer *bo;
|
||||
unsigned int format;
|
||||
unsigned int pitch;
|
||||
unsigned int cpp;
|
||||
|
||||
switch (surface->format) {
|
||||
case PIPE_FORMAT_Z16_UNORM:
|
||||
format = BRW_DEPTHFORMAT_D16_UNORM;
|
||||
cpp = 2;
|
||||
break;
|
||||
case PIPE_FORMAT_X8Z24_UNORM:
|
||||
case PIPE_FORMAT_S8Z24_UNORM:
|
||||
format = BRW_DEPTHFORMAT_D24_UNORM_S8_UINT;
|
||||
cpp = 4;
|
||||
break;
|
||||
case PIPE_FORMAT_Z32_FLOAT:
|
||||
format = BRW_DEPTHFORMAT_D32_FLOAT;
|
||||
cpp = 4;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return PIPE_ERROR_BAD_INPUT;
|
||||
}
|
||||
|
||||
bo = brw_surface(surface)->bo;
|
||||
pitch = brw_surface(surface)->pitch;
|
||||
|
||||
BEGIN_BATCH(len, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH(CMD_DEPTH_BUFFER << 16 | (len - 2));
|
||||
OUT_BATCH(((pitch * cpp) - 1) |
|
||||
(format << 18) |
|
||||
(BRW_TILEWALK_YMAJOR << 26) |
|
||||
((surface->layout != PIPE_SURFACE_LAYOUT_LINEAR) << 27) |
|
||||
(BRW_SURFACE_2D << 29));
|
||||
OUT_RELOC(bo,
|
||||
BRW_USAGE_DEPTH_BUFFER,
|
||||
surface->offset);
|
||||
OUT_BATCH((BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1) |
|
||||
((pitch - 1) << 6) |
|
||||
((surface->height - 1) << 19));
|
||||
OUT_BATCH(0);
|
||||
|
||||
if (BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw))
|
||||
OUT_BATCH(0);
|
||||
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_depthbuffer = {
|
||||
.dirty = {
|
||||
.mesa = PIPE_NEW_DEPTH_BUFFER,
|
||||
.brw = BRW_NEW_BATCH,
|
||||
.cache = 0,
|
||||
},
|
||||
.prepare = prepare_depthbuffer,
|
||||
.emit = emit_depthbuffer,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Polygon stipple packet
|
||||
*/
|
||||
|
||||
static int upload_polygon_stipple(struct brw_context *brw)
|
||||
{
|
||||
BRW_CACHED_BATCH_STRUCT(brw, &brw->curr.bps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_polygon_stipple = {
|
||||
.dirty = {
|
||||
.mesa = PIPE_NEW_POLYGON_STIPPLE,
|
||||
.brw = 0,
|
||||
.cache = 0
|
||||
},
|
||||
.emit = upload_polygon_stipple
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Line stipple packet
|
||||
*/
|
||||
|
||||
static int upload_line_stipple(struct brw_context *brw)
|
||||
{
|
||||
const struct brw_line_stipple *bls = &brw->curr.rast->bls;
|
||||
if (bls->header.opcode) {
|
||||
BRW_CACHED_BATCH_STRUCT(brw, bls);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_line_stipple = {
|
||||
.dirty = {
|
||||
.mesa = PIPE_NEW_RAST,
|
||||
.brw = 0,
|
||||
.cache = 0
|
||||
},
|
||||
.emit = upload_line_stipple
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Misc invarient state packets
|
||||
*/
|
||||
|
||||
static int upload_invarient_state( struct brw_context *brw )
|
||||
{
|
||||
{
|
||||
/* 0x61040000 Pipeline Select */
|
||||
/* PipelineSelect : 0 */
|
||||
struct brw_pipeline_select ps;
|
||||
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
if (BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw))
|
||||
ps.header.opcode = CMD_PIPELINE_SELECT_GM45;
|
||||
else
|
||||
ps.header.opcode = CMD_PIPELINE_SELECT_965;
|
||||
ps.header.pipeline_select = 0;
|
||||
BRW_BATCH_STRUCT(brw, &ps);
|
||||
}
|
||||
|
||||
{
|
||||
struct brw_global_depth_offset_clamp gdo;
|
||||
memset(&gdo, 0, sizeof(gdo));
|
||||
|
||||
/* Disable depth offset clamping.
|
||||
*/
|
||||
gdo.header.opcode = CMD_GLOBAL_DEPTH_OFFSET_CLAMP;
|
||||
gdo.header.length = sizeof(gdo)/4 - 2;
|
||||
gdo.depth_offset_clamp = 0.0;
|
||||
|
||||
BRW_BATCH_STRUCT(brw, &gdo);
|
||||
}
|
||||
|
||||
|
||||
/* 0x61020000 State Instruction Pointer */
|
||||
{
|
||||
struct brw_system_instruction_pointer sip;
|
||||
memset(&sip, 0, sizeof(sip));
|
||||
|
||||
sip.header.opcode = CMD_STATE_INSN_POINTER;
|
||||
sip.header.length = 0;
|
||||
sip.bits0.pad = 0;
|
||||
sip.bits0.system_instruction_pointer = 0;
|
||||
BRW_BATCH_STRUCT(brw, &sip);
|
||||
}
|
||||
|
||||
/* VF Statistics */
|
||||
{
|
||||
struct brw_vf_statistics vfs;
|
||||
memset(&vfs, 0, sizeof(vfs));
|
||||
|
||||
if (BRW_IS_G4X(brw) || BRW_IS_IGDNG(brw))
|
||||
vfs.opcode = CMD_VF_STATISTICS_GM45;
|
||||
else
|
||||
vfs.opcode = CMD_VF_STATISTICS_965;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_STATS)
|
||||
vfs.statistics_enable = 1;
|
||||
|
||||
BRW_BATCH_STRUCT(brw, &vfs);
|
||||
}
|
||||
|
||||
if (!BRW_IS_965(brw))
|
||||
{
|
||||
struct brw_aa_line_parameters balp;
|
||||
|
||||
/* use legacy aa line coverage computation */
|
||||
memset(&balp, 0, sizeof(balp));
|
||||
balp.header.opcode = CMD_AA_LINE_PARAMETERS;
|
||||
balp.header.length = sizeof(balp) / 4 - 2;
|
||||
|
||||
BRW_BATCH_STRUCT(brw, &balp);
|
||||
}
|
||||
|
||||
{
|
||||
struct brw_polygon_stipple_offset bpso;
|
||||
|
||||
/* This is invarient state in gallium:
|
||||
*/
|
||||
memset(&bpso, 0, sizeof(bpso));
|
||||
bpso.header.opcode = CMD_POLY_STIPPLE_OFFSET;
|
||||
bpso.header.length = sizeof(bpso)/4-2;
|
||||
bpso.bits0.y_offset = 0;
|
||||
bpso.bits0.x_offset = 0;
|
||||
|
||||
BRW_BATCH_STRUCT(brw, &bpso);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_invarient_state = {
|
||||
.dirty = {
|
||||
.mesa = 0,
|
||||
.brw = BRW_NEW_CONTEXT,
|
||||
.cache = 0
|
||||
},
|
||||
.emit = upload_invarient_state
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* State base address
|
||||
*/
|
||||
|
||||
/**
|
||||
* Define the base addresses which some state is referenced from.
|
||||
*
|
||||
* This allows us to avoid having to emit relocations in many places for
|
||||
* cached state, and instead emit pointers inside of large, mostly-static
|
||||
* state pools. This comes at the expense of memory, and more expensive cache
|
||||
* misses.
|
||||
*/
|
||||
static int upload_state_base_address( struct brw_context *brw )
|
||||
{
|
||||
/* Output the structure (brw_state_base_address) directly to the
|
||||
* batchbuffer, so we can emit relocations inline.
|
||||
*/
|
||||
if (BRW_IS_IGDNG(brw)) {
|
||||
BEGIN_BATCH(8, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (8 - 2));
|
||||
OUT_BATCH(1); /* General state base address */
|
||||
OUT_BATCH(1); /* Surface state base address */
|
||||
OUT_BATCH(1); /* Indirect object base address */
|
||||
OUT_BATCH(1); /* Instruction base address */
|
||||
OUT_BATCH(1); /* General state upper bound */
|
||||
OUT_BATCH(1); /* Indirect object upper bound */
|
||||
OUT_BATCH(1); /* Instruction access upper bound */
|
||||
ADVANCE_BATCH();
|
||||
} else {
|
||||
BEGIN_BATCH(6, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (6 - 2));
|
||||
OUT_BATCH(1); /* General state base address */
|
||||
OUT_BATCH(1); /* Surface state base address */
|
||||
OUT_BATCH(1); /* Indirect object base address */
|
||||
OUT_BATCH(1); /* General state upper bound */
|
||||
OUT_BATCH(1); /* Indirect object upper bound */
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_state_base_address = {
|
||||
.dirty = {
|
||||
.mesa = 0,
|
||||
.brw = BRW_NEW_CONTEXT,
|
||||
.cache = 0,
|
||||
},
|
||||
.emit = upload_state_base_address
|
||||
};
|
||||
@@ -0,0 +1,208 @@
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_debug.h"
|
||||
|
||||
static int translate_logicop(unsigned logicop)
|
||||
{
|
||||
switch (logicop) {
|
||||
case PIPE_LOGICOP_CLEAR:
|
||||
return BRW_LOGICOPFUNCTION_CLEAR;
|
||||
case PIPE_LOGICOP_AND:
|
||||
return BRW_LOGICOPFUNCTION_AND;
|
||||
case PIPE_LOGICOP_AND_REVERSE:
|
||||
return BRW_LOGICOPFUNCTION_AND_REVERSE;
|
||||
case PIPE_LOGICOP_COPY:
|
||||
return BRW_LOGICOPFUNCTION_COPY;
|
||||
case PIPE_LOGICOP_COPY_INVERTED:
|
||||
return BRW_LOGICOPFUNCTION_COPY_INVERTED;
|
||||
case PIPE_LOGICOP_AND_INVERTED:
|
||||
return BRW_LOGICOPFUNCTION_AND_INVERTED;
|
||||
case PIPE_LOGICOP_NOOP:
|
||||
return BRW_LOGICOPFUNCTION_NOOP;
|
||||
case PIPE_LOGICOP_XOR:
|
||||
return BRW_LOGICOPFUNCTION_XOR;
|
||||
case PIPE_LOGICOP_OR:
|
||||
return BRW_LOGICOPFUNCTION_OR;
|
||||
case PIPE_LOGICOP_OR_INVERTED:
|
||||
return BRW_LOGICOPFUNCTION_OR_INVERTED;
|
||||
case PIPE_LOGICOP_NOR:
|
||||
return BRW_LOGICOPFUNCTION_NOR;
|
||||
case PIPE_LOGICOP_EQUIV:
|
||||
return BRW_LOGICOPFUNCTION_EQUIV;
|
||||
case PIPE_LOGICOP_INVERT:
|
||||
return BRW_LOGICOPFUNCTION_INVERT;
|
||||
case PIPE_LOGICOP_OR_REVERSE:
|
||||
return BRW_LOGICOPFUNCTION_OR_REVERSE;
|
||||
case PIPE_LOGICOP_NAND:
|
||||
return BRW_LOGICOPFUNCTION_NAND;
|
||||
case PIPE_LOGICOP_SET:
|
||||
return BRW_LOGICOPFUNCTION_SET;
|
||||
default:
|
||||
assert(0);
|
||||
return BRW_LOGICOPFUNCTION_SET;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static unsigned translate_blend_equation( unsigned mode )
|
||||
{
|
||||
switch (mode) {
|
||||
case PIPE_BLEND_ADD:
|
||||
return BRW_BLENDFUNCTION_ADD;
|
||||
case PIPE_BLEND_MIN:
|
||||
return BRW_BLENDFUNCTION_MIN;
|
||||
case PIPE_BLEND_MAX:
|
||||
return BRW_BLENDFUNCTION_MAX;
|
||||
case PIPE_BLEND_SUBTRACT:
|
||||
return BRW_BLENDFUNCTION_SUBTRACT;
|
||||
case PIPE_BLEND_REVERSE_SUBTRACT:
|
||||
return BRW_BLENDFUNCTION_REVERSE_SUBTRACT;
|
||||
default:
|
||||
assert(0);
|
||||
return BRW_BLENDFUNCTION_ADD;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned translate_blend_factor( unsigned factor )
|
||||
{
|
||||
switch(factor) {
|
||||
case PIPE_BLENDFACTOR_ZERO:
|
||||
return BRW_BLENDFACTOR_ZERO;
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA:
|
||||
return BRW_BLENDFACTOR_SRC_ALPHA;
|
||||
case PIPE_BLENDFACTOR_ONE:
|
||||
return BRW_BLENDFACTOR_ONE;
|
||||
case PIPE_BLENDFACTOR_SRC_COLOR:
|
||||
return BRW_BLENDFACTOR_SRC_COLOR;
|
||||
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
|
||||
return BRW_BLENDFACTOR_INV_SRC_COLOR;
|
||||
case PIPE_BLENDFACTOR_DST_COLOR:
|
||||
return BRW_BLENDFACTOR_DST_COLOR;
|
||||
case PIPE_BLENDFACTOR_INV_DST_COLOR:
|
||||
return BRW_BLENDFACTOR_INV_DST_COLOR;
|
||||
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
|
||||
return BRW_BLENDFACTOR_INV_SRC_ALPHA;
|
||||
case PIPE_BLENDFACTOR_DST_ALPHA:
|
||||
return BRW_BLENDFACTOR_DST_ALPHA;
|
||||
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
|
||||
return BRW_BLENDFACTOR_INV_DST_ALPHA;
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
|
||||
return BRW_BLENDFACTOR_SRC_ALPHA_SATURATE;
|
||||
case PIPE_BLENDFACTOR_CONST_COLOR:
|
||||
return BRW_BLENDFACTOR_CONST_COLOR;
|
||||
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
|
||||
return BRW_BLENDFACTOR_INV_CONST_COLOR;
|
||||
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
||||
return BRW_BLENDFACTOR_CONST_ALPHA;
|
||||
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
|
||||
return BRW_BLENDFACTOR_INV_CONST_ALPHA;
|
||||
default:
|
||||
assert(0);
|
||||
return BRW_BLENDFACTOR_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
static void *brw_create_blend_state( struct pipe_context *pipe,
|
||||
const struct pipe_blend_state *templ )
|
||||
{
|
||||
struct brw_blend_state *blend = CALLOC_STRUCT(brw_blend_state);
|
||||
if (blend == NULL)
|
||||
return NULL;
|
||||
|
||||
if (templ->logicop_enable) {
|
||||
blend->cc2.logicop_enable = 1;
|
||||
blend->cc5.logicop_func = translate_logicop(templ->logicop_func);
|
||||
}
|
||||
else if (templ->blend_enable) {
|
||||
blend->cc6.dest_blend_factor = translate_blend_factor(templ->rgb_dst_factor);
|
||||
blend->cc6.src_blend_factor = translate_blend_factor(templ->rgb_src_factor);
|
||||
blend->cc6.blend_function = translate_blend_equation(templ->rgb_func);
|
||||
|
||||
blend->cc5.ia_dest_blend_factor = translate_blend_factor(templ->alpha_dst_factor);
|
||||
blend->cc5.ia_src_blend_factor = translate_blend_factor(templ->alpha_src_factor);
|
||||
blend->cc5.ia_blend_function = translate_blend_equation(templ->alpha_func);
|
||||
|
||||
blend->cc3.blend_enable = 1;
|
||||
blend->cc3.ia_blend_enable =
|
||||
(blend->cc6.dest_blend_factor != blend->cc5.ia_dest_blend_factor ||
|
||||
blend->cc6.src_blend_factor != blend->cc5.ia_src_blend_factor ||
|
||||
blend->cc6.blend_function != blend->cc5.ia_blend_function);
|
||||
|
||||
/* Per-surface blend enables, currently just follow global
|
||||
* state:
|
||||
*/
|
||||
blend->ss0.color_blend = 1;
|
||||
}
|
||||
|
||||
blend->cc5.dither_enable = templ->dither;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_STATS)
|
||||
blend->cc5.statistics_enable = 1;
|
||||
|
||||
/* Per-surface color mask -- just follow global state:
|
||||
*/
|
||||
blend->ss0.writedisable_red = (templ->colormask & PIPE_MASK_R) ? 0 : 1;
|
||||
blend->ss0.writedisable_green = (templ->colormask & PIPE_MASK_G) ? 0 : 1;
|
||||
blend->ss0.writedisable_blue = (templ->colormask & PIPE_MASK_B) ? 0 : 1;
|
||||
blend->ss0.writedisable_alpha = (templ->colormask & PIPE_MASK_A) ? 0 : 1;
|
||||
|
||||
return (void *)blend;
|
||||
}
|
||||
|
||||
static void brw_bind_blend_state(struct pipe_context *pipe,
|
||||
void *cso)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
brw->curr.blend = (const struct brw_blend_state *)cso;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_BLEND;
|
||||
}
|
||||
|
||||
static void brw_delete_blend_state(struct pipe_context *pipe,
|
||||
void *cso)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
assert((const void *)cso != (const void *)brw->curr.blend);
|
||||
FREE(cso);
|
||||
}
|
||||
|
||||
|
||||
static void brw_set_blend_color(struct pipe_context *pipe,
|
||||
const struct pipe_blend_color *blend_color)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
struct brw_blend_constant_color *bcc = &brw->curr.bcc;
|
||||
|
||||
bcc->blend_constant_color[0] = blend_color->color[0];
|
||||
bcc->blend_constant_color[1] = blend_color->color[1];
|
||||
bcc->blend_constant_color[2] = blend_color->color[2];
|
||||
bcc->blend_constant_color[3] = blend_color->color[3];
|
||||
|
||||
brw->state.dirty.mesa |= PIPE_NEW_BLEND_COLOR;
|
||||
}
|
||||
|
||||
|
||||
void brw_pipe_blend_init( struct brw_context *brw )
|
||||
{
|
||||
brw->base.set_blend_color = brw_set_blend_color;
|
||||
brw->base.create_blend_state = brw_create_blend_state;
|
||||
brw->base.bind_blend_state = brw_bind_blend_state;
|
||||
brw->base.delete_blend_state = brw_delete_blend_state;
|
||||
|
||||
{
|
||||
struct brw_blend_constant_color *bcc = &brw->curr.bcc;
|
||||
|
||||
memset(bcc, 0, sizeof(*bcc));
|
||||
bcc->header.opcode = CMD_BLEND_CONSTANT_COLOR;
|
||||
bcc->header.length = sizeof(*bcc)/4-2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void brw_pipe_blend_cleanup( struct brw_context *brw )
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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 "util/u_pack_color.h"
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_screen.h"
|
||||
#include "brw_context.h"
|
||||
|
||||
#define MASK16 0xffff
|
||||
#define MASK24 0xffffff
|
||||
|
||||
|
||||
/**
|
||||
* Use blitting to clear the renderbuffers named by 'flags'.
|
||||
* Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field
|
||||
* since that might include software renderbuffers or renderbuffers
|
||||
* which we're clearing with triangles.
|
||||
* \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear
|
||||
*/
|
||||
static enum pipe_error
|
||||
try_clear( struct brw_context *brw,
|
||||
struct brw_surface *surface,
|
||||
unsigned value )
|
||||
{
|
||||
uint32_t BR13, CMD;
|
||||
int x1 = 0;
|
||||
int y1 = 0;
|
||||
int x2 = surface->base.width;
|
||||
int y2 = surface->base.height;
|
||||
int pitch = surface->pitch;
|
||||
int cpp = surface->cpp;
|
||||
|
||||
if (x2 == 0 || y2 == 0)
|
||||
return 0;
|
||||
|
||||
debug_printf("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
|
||||
__FUNCTION__,
|
||||
(void *)surface->bo, pitch * cpp,
|
||||
surface->base.offset,
|
||||
x1, y1, x2 - x1, y2 - y1);
|
||||
|
||||
BR13 = 0xf0 << 16;
|
||||
CMD = XY_COLOR_BLT_CMD | XY_BLT_WRITE_RGB | XY_BLT_WRITE_ALPHA;
|
||||
|
||||
/* Setup the blit command */
|
||||
if (cpp == 4) {
|
||||
BR13 |= BR13_8888;
|
||||
CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
|
||||
}
|
||||
else {
|
||||
assert(cpp == 2);
|
||||
BR13 |= BR13_565;
|
||||
}
|
||||
|
||||
/* XXX: nasty hack for clearing depth buffers
|
||||
*/
|
||||
if (surface->tiling == BRW_TILING_Y) {
|
||||
x2 = pitch;
|
||||
}
|
||||
|
||||
if (surface->tiling == BRW_TILING_X) {
|
||||
CMD |= XY_DST_TILED;
|
||||
pitch /= 4;
|
||||
}
|
||||
|
||||
BR13 |= (pitch * cpp);
|
||||
|
||||
BEGIN_BATCH(6, 0);
|
||||
OUT_BATCH(CMD);
|
||||
OUT_BATCH(BR13);
|
||||
OUT_BATCH((y1 << 16) | x1);
|
||||
OUT_BATCH((y2 << 16) | x2);
|
||||
OUT_RELOC(surface->bo,
|
||||
BRW_USAGE_BLIT_DEST,
|
||||
surface->base.offset);
|
||||
OUT_BATCH(value);
|
||||
ADVANCE_BATCH();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void color_clear(struct brw_context *brw,
|
||||
struct brw_surface *bsurface,
|
||||
const float *rgba )
|
||||
{
|
||||
enum pipe_error ret;
|
||||
unsigned value;
|
||||
|
||||
util_pack_color( rgba, bsurface->base.format, &value );
|
||||
|
||||
if (bsurface->cpp == 2)
|
||||
value |= value << 16;
|
||||
|
||||
ret = try_clear( brw, bsurface, value );
|
||||
|
||||
if (ret != 0) {
|
||||
brw_context_flush( brw );
|
||||
ret = try_clear( brw, bsurface, value );
|
||||
assert( ret == 0 );
|
||||
}
|
||||
}
|
||||
|
||||
static void zstencil_clear(struct brw_context *brw,
|
||||
struct brw_surface *bsurface,
|
||||
double depth,
|
||||
unsigned stencil )
|
||||
{
|
||||
enum pipe_error ret;
|
||||
unsigned value;
|
||||
|
||||
switch (bsurface->base.format) {
|
||||
case PIPE_FORMAT_X8Z24_UNORM:
|
||||
case PIPE_FORMAT_S8Z24_UNORM:
|
||||
value = ((unsigned)(depth * MASK24) & MASK24);
|
||||
break;
|
||||
case PIPE_FORMAT_Z16_UNORM:
|
||||
value = ((unsigned)(depth * MASK16) & MASK16);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (bsurface->base.format) {
|
||||
case PIPE_FORMAT_X8Z24_UNORM:
|
||||
case PIPE_FORMAT_S8Z24_UNORM:
|
||||
value = value | (stencil << 24);
|
||||
break;
|
||||
|
||||
case PIPE_FORMAT_Z16_UNORM:
|
||||
value = value | (value << 16);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = try_clear( brw, bsurface, value );
|
||||
|
||||
if (ret != 0) {
|
||||
brw_context_flush( brw );
|
||||
ret = try_clear( brw, bsurface, value );
|
||||
assert( ret == 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Clear the given surface to the specified value.
|
||||
* No masking, no scissor (clear entire buffer).
|
||||
*/
|
||||
static void brw_clear(struct pipe_context *pipe,
|
||||
unsigned buffers,
|
||||
const float *rgba,
|
||||
double depth,
|
||||
unsigned stencil)
|
||||
{
|
||||
struct brw_context *brw = brw_context( pipe );
|
||||
int i;
|
||||
|
||||
if (buffers & PIPE_CLEAR_COLOR) {
|
||||
for (i = 0; i < brw->curr.fb.nr_cbufs; i++) {
|
||||
color_clear( brw,
|
||||
brw_surface(brw->curr.fb.cbufs[i]),
|
||||
rgba );
|
||||
}
|
||||
}
|
||||
|
||||
if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
|
||||
if (brw->curr.fb.zsbuf) {
|
||||
zstencil_clear( brw,
|
||||
brw_surface(brw->curr.fb.zsbuf),
|
||||
depth, stencil );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void brw_pipe_clear_init( struct brw_context *brw )
|
||||
{
|
||||
brw->base.clear = brw_clear;
|
||||
}
|
||||
|
||||
|
||||
void brw_pipe_clear_cleanup( struct brw_context *brw )
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_defines.h"
|
||||
|
||||
/* XXX: Fixme - include this to get IZ_ defines
|
||||
*/
|
||||
#include "brw_wm.h"
|
||||
|
||||
static unsigned brw_translate_compare_func(unsigned func)
|
||||
{
|
||||
switch (func) {
|
||||
case PIPE_FUNC_NEVER:
|
||||
return BRW_COMPAREFUNCTION_NEVER;
|
||||
case PIPE_FUNC_LESS:
|
||||
return BRW_COMPAREFUNCTION_LESS;
|
||||
case PIPE_FUNC_LEQUAL:
|
||||
return BRW_COMPAREFUNCTION_LEQUAL;
|
||||
case PIPE_FUNC_GREATER:
|
||||
return BRW_COMPAREFUNCTION_GREATER;
|
||||
case PIPE_FUNC_GEQUAL:
|
||||
return BRW_COMPAREFUNCTION_GEQUAL;
|
||||
case PIPE_FUNC_NOTEQUAL:
|
||||
return BRW_COMPAREFUNCTION_NOTEQUAL;
|
||||
case PIPE_FUNC_EQUAL:
|
||||
return BRW_COMPAREFUNCTION_EQUAL;
|
||||
case PIPE_FUNC_ALWAYS:
|
||||
return BRW_COMPAREFUNCTION_ALWAYS;
|
||||
default:
|
||||
assert(0);
|
||||
return BRW_COMPAREFUNCTION_ALWAYS;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned translate_stencil_op(unsigned op)
|
||||
{
|
||||
switch (op) {
|
||||
case PIPE_STENCIL_OP_KEEP:
|
||||
return BRW_STENCILOP_KEEP;
|
||||
case PIPE_STENCIL_OP_ZERO:
|
||||
return BRW_STENCILOP_ZERO;
|
||||
case PIPE_STENCIL_OP_REPLACE:
|
||||
return BRW_STENCILOP_REPLACE;
|
||||
case PIPE_STENCIL_OP_INCR:
|
||||
return BRW_STENCILOP_INCRSAT;
|
||||
case PIPE_STENCIL_OP_DECR:
|
||||
return BRW_STENCILOP_DECRSAT;
|
||||
case PIPE_STENCIL_OP_INCR_WRAP:
|
||||
return BRW_STENCILOP_INCR;
|
||||
case PIPE_STENCIL_OP_DECR_WRAP:
|
||||
return BRW_STENCILOP_DECR;
|
||||
case PIPE_STENCIL_OP_INVERT:
|
||||
return BRW_STENCILOP_INVERT;
|
||||
default:
|
||||
assert(0);
|
||||
return BRW_STENCILOP_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
static void create_bcc_state( struct brw_depth_stencil_state *zstencil,
|
||||
const struct pipe_depth_stencil_alpha_state *templ )
|
||||
{
|
||||
if (templ->stencil[0].enabled) {
|
||||
zstencil->cc0.stencil_enable = 1;
|
||||
zstencil->cc0.stencil_func =
|
||||
brw_translate_compare_func(templ->stencil[0].func);
|
||||
zstencil->cc0.stencil_fail_op =
|
||||
translate_stencil_op(templ->stencil[0].fail_op);
|
||||
zstencil->cc0.stencil_pass_depth_fail_op =
|
||||
translate_stencil_op(templ->stencil[0].zfail_op);
|
||||
zstencil->cc0.stencil_pass_depth_pass_op =
|
||||
translate_stencil_op(templ->stencil[0].zpass_op);
|
||||
zstencil->cc1.stencil_ref = templ->stencil[0].ref_value;
|
||||
zstencil->cc1.stencil_write_mask = templ->stencil[0].writemask;
|
||||
zstencil->cc1.stencil_test_mask = templ->stencil[0].valuemask;
|
||||
|
||||
if (templ->stencil[1].enabled) {
|
||||
zstencil->cc0.bf_stencil_enable = 1;
|
||||
zstencil->cc0.bf_stencil_func =
|
||||
brw_translate_compare_func(templ->stencil[1].func);
|
||||
zstencil->cc0.bf_stencil_fail_op =
|
||||
translate_stencil_op(templ->stencil[1].fail_op);
|
||||
zstencil->cc0.bf_stencil_pass_depth_fail_op =
|
||||
translate_stencil_op(templ->stencil[1].zfail_op);
|
||||
zstencil->cc0.bf_stencil_pass_depth_pass_op =
|
||||
translate_stencil_op(templ->stencil[1].zpass_op);
|
||||
zstencil->cc1.bf_stencil_ref = templ->stencil[1].ref_value;
|
||||
zstencil->cc2.bf_stencil_write_mask = templ->stencil[1].writemask;
|
||||
zstencil->cc2.bf_stencil_test_mask = templ->stencil[1].valuemask;
|
||||
}
|
||||
|
||||
zstencil->cc0.stencil_write_enable = (zstencil->cc1.stencil_write_mask ||
|
||||
zstencil->cc2.bf_stencil_write_mask);
|
||||
}
|
||||
|
||||
|
||||
if (templ->alpha.enabled) {
|
||||
zstencil->cc3.alpha_test = 1;
|
||||
zstencil->cc3.alpha_test_func = brw_translate_compare_func(templ->alpha.func);
|
||||
zstencil->cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8;
|
||||
zstencil->cc7.alpha_ref.ub[0] = float_to_ubyte(templ->alpha.ref_value);
|
||||
}
|
||||
|
||||
if (templ->depth.enabled) {
|
||||
zstencil->cc2.depth_test = 1;
|
||||
zstencil->cc2.depth_test_function = brw_translate_compare_func(templ->depth.func);
|
||||
zstencil->cc2.depth_write_enable = templ->depth.writemask;
|
||||
}
|
||||
}
|
||||
|
||||
static void create_wm_iz_state( struct brw_depth_stencil_state *zstencil )
|
||||
{
|
||||
if (zstencil->cc3.alpha_test)
|
||||
zstencil->iz_lookup |= IZ_PS_KILL_ALPHATEST_BIT;
|
||||
|
||||
if (zstencil->cc2.depth_test)
|
||||
zstencil->iz_lookup |= IZ_DEPTH_TEST_ENABLE_BIT;
|
||||
|
||||
if (zstencil->cc2.depth_write_enable)
|
||||
zstencil->iz_lookup |= IZ_DEPTH_WRITE_ENABLE_BIT;
|
||||
|
||||
if (zstencil->cc0.stencil_enable)
|
||||
zstencil->iz_lookup |= IZ_STENCIL_TEST_ENABLE_BIT;
|
||||
|
||||
if (zstencil->cc0.stencil_write_enable)
|
||||
zstencil->iz_lookup |= IZ_STENCIL_WRITE_ENABLE_BIT;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
brw_create_depth_stencil_state( struct pipe_context *pipe,
|
||||
const struct pipe_depth_stencil_alpha_state *templ )
|
||||
{
|
||||
struct brw_depth_stencil_state *zstencil = CALLOC_STRUCT(brw_depth_stencil_state);
|
||||
|
||||
create_bcc_state( zstencil, templ );
|
||||
create_wm_iz_state( zstencil );
|
||||
|
||||
return (void *)zstencil;
|
||||
}
|
||||
|
||||
|
||||
static void brw_bind_depth_stencil_state(struct pipe_context *pipe,
|
||||
void *cso)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
brw->curr.zstencil = (const struct brw_depth_stencil_state *)cso;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_DEPTH_STENCIL_ALPHA;
|
||||
}
|
||||
|
||||
static void brw_delete_depth_stencil_state(struct pipe_context *pipe,
|
||||
void *cso)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
assert((const void *)cso != (const void *)brw->curr.zstencil);
|
||||
FREE(cso);
|
||||
}
|
||||
|
||||
|
||||
void brw_pipe_depth_stencil_init( struct brw_context *brw )
|
||||
{
|
||||
brw->base.create_depth_stencil_alpha_state = brw_create_depth_stencil_state;
|
||||
brw->base.bind_depth_stencil_alpha_state = brw_bind_depth_stencil_state;
|
||||
brw->base.delete_depth_stencil_alpha_state = brw_delete_depth_stencil_state;
|
||||
}
|
||||
|
||||
void brw_pipe_depth_stencil_cleanup( struct brw_context *brw )
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "util/u_math.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
|
||||
/**
|
||||
* called from intelDrawBuffer()
|
||||
*/
|
||||
static void brw_set_framebuffer_state( struct pipe_context *pipe,
|
||||
const struct pipe_framebuffer_state *fb )
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
unsigned i;
|
||||
|
||||
/* Dimensions:
|
||||
*/
|
||||
if (brw->curr.fb.width != fb->width ||
|
||||
brw->curr.fb.height != fb->height) {
|
||||
brw->curr.fb.width = fb->width;
|
||||
brw->curr.fb.height = fb->height;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_FRAMEBUFFER_DIMENSIONS;
|
||||
}
|
||||
|
||||
/* Z/Stencil
|
||||
*/
|
||||
if (brw->curr.fb.zsbuf != fb->zsbuf) {
|
||||
pipe_surface_reference(&brw->curr.fb.zsbuf, fb->zsbuf);
|
||||
brw->state.dirty.mesa |= PIPE_NEW_DEPTH_BUFFER;
|
||||
}
|
||||
|
||||
/* Color buffers:
|
||||
*/
|
||||
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
|
||||
if (brw->curr.fb.cbufs[i] != fb->cbufs[i]) {
|
||||
brw->state.dirty.mesa |= PIPE_NEW_COLOR_BUFFERS;
|
||||
pipe_surface_reference(&brw->curr.fb.cbufs[i], fb->cbufs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (brw->curr.fb.nr_cbufs != fb->nr_cbufs) {
|
||||
brw->curr.fb.nr_cbufs = MIN2(BRW_MAX_DRAW_BUFFERS, fb->nr_cbufs);
|
||||
brw->state.dirty.mesa |= PIPE_NEW_NR_CBUFS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void brw_set_viewport_state( struct pipe_context *pipe,
|
||||
const struct pipe_viewport_state *viewport )
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
|
||||
brw->curr.viewport = *viewport;
|
||||
brw->curr.ccv.min_depth = 0.0; /* XXX: near */
|
||||
brw->curr.ccv.max_depth = 1.0; /* XXX: far */
|
||||
|
||||
brw->state.dirty.mesa |= PIPE_NEW_VIEWPORT;
|
||||
}
|
||||
|
||||
|
||||
void brw_pipe_framebuffer_init( struct brw_context *brw )
|
||||
{
|
||||
brw->base.set_framebuffer_state = brw_set_framebuffer_state;
|
||||
brw->base.set_viewport_state = brw_set_viewport_state;
|
||||
}
|
||||
|
||||
void brw_pipe_framebuffer_cleanup( struct brw_context *brw )
|
||||
{
|
||||
struct pipe_framebuffer_state *fb = &brw->curr.fb;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
|
||||
pipe_surface_reference(&fb->cbufs[i], NULL);
|
||||
}
|
||||
|
||||
pipe_surface_reference(&fb->zsbuf, NULL);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
|
||||
#include "util/u_upload_mgr.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_screen.h"
|
||||
#include "brw_batchbuffer.h"
|
||||
|
||||
|
||||
|
||||
/* All batchbuffer flushes must go through this function.
|
||||
*/
|
||||
void brw_context_flush( struct brw_context *brw )
|
||||
{
|
||||
/*
|
||||
*
|
||||
*/
|
||||
brw_emit_query_end(brw);
|
||||
|
||||
/* Move to the end of the current upload buffer so that we'll force choosing
|
||||
* a new buffer next time.
|
||||
*/
|
||||
u_upload_flush( brw->vb.upload_vertex );
|
||||
u_upload_flush( brw->vb.upload_index );
|
||||
|
||||
_brw_batchbuffer_flush( brw->batch, __FILE__, __LINE__ );
|
||||
|
||||
/* Mark all context state as needing to be re-emitted.
|
||||
* This is probably not as severe as on 915, since almost all of our state
|
||||
* is just in referenced buffers.
|
||||
*/
|
||||
brw->state.dirty.brw |= BRW_NEW_CONTEXT;
|
||||
brw->state.dirty.mesa |= ~0;
|
||||
brw->state.dirty.brw |= ~0;
|
||||
brw->state.dirty.cache |= ~0;
|
||||
|
||||
brw->curbe.need_new_bo = GL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
brw_flush( struct pipe_context *pipe,
|
||||
unsigned flags,
|
||||
struct pipe_fence_handle **fence )
|
||||
{
|
||||
brw_context_flush( brw_context( pipe ) );
|
||||
if (fence)
|
||||
*fence = NULL;
|
||||
}
|
||||
|
||||
static unsigned brw_is_buffer_referenced(struct pipe_context *pipe,
|
||||
struct pipe_buffer *buffer)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
struct brw_screen *bscreen = brw_screen(brw->base.screen);
|
||||
|
||||
return brw_is_buffer_referenced_by_bo( bscreen,
|
||||
buffer,
|
||||
brw->batch->buf );
|
||||
}
|
||||
|
||||
static unsigned brw_is_texture_referenced(struct pipe_context *pipe,
|
||||
struct pipe_texture *texture,
|
||||
unsigned face,
|
||||
unsigned level)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
struct brw_screen *bscreen = brw_screen(brw->base.screen);
|
||||
|
||||
return brw_is_texture_referenced_by_bo( bscreen,
|
||||
texture, face, level,
|
||||
brw->batch->buf );
|
||||
}
|
||||
|
||||
void brw_pipe_flush_init( struct brw_context *brw )
|
||||
{
|
||||
brw->base.flush = brw_flush;
|
||||
brw->base.is_buffer_referenced = brw_is_buffer_referenced;
|
||||
brw->base.is_texture_referenced = brw_is_texture_referenced;
|
||||
}
|
||||
|
||||
|
||||
void brw_pipe_flush_cleanup( struct brw_context *brw )
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_structs.h"
|
||||
#include "brw_defines.h"
|
||||
|
||||
static void brw_set_polygon_stipple( struct pipe_context *pipe,
|
||||
const struct pipe_poly_stipple *stip )
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
struct brw_polygon_stipple *bps = &brw->curr.bps;
|
||||
GLuint i;
|
||||
|
||||
memset(bps, 0, sizeof *bps);
|
||||
bps->header.opcode = CMD_POLY_STIPPLE_PATTERN;
|
||||
bps->header.length = sizeof *bps/4-2;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
bps->stipple[i] = stip->stipple[i]; /* don't invert */
|
||||
|
||||
brw->state.dirty.mesa |= PIPE_NEW_POLYGON_STIPPLE;
|
||||
}
|
||||
|
||||
|
||||
static void brw_set_scissor_state( struct pipe_context *pipe,
|
||||
const struct pipe_scissor_state *scissor )
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
|
||||
brw->curr.scissor = *scissor;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_SCISSOR;
|
||||
}
|
||||
|
||||
|
||||
static void brw_set_clip_state( struct pipe_context *pipe,
|
||||
const struct pipe_clip_state *clip )
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
|
||||
brw->curr.ucp = *clip;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_CLIP;
|
||||
}
|
||||
|
||||
|
||||
void brw_pipe_misc_init( struct brw_context *brw )
|
||||
{
|
||||
brw->base.set_polygon_stipple = brw_set_polygon_stipple;
|
||||
brw->base.set_scissor_state = brw_set_scissor_state;
|
||||
brw->base.set_clip_state = brw_set_clip_state;
|
||||
}
|
||||
|
||||
|
||||
void brw_pipe_misc_cleanup( struct brw_context *brw )
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright © 2008 Intel Corporation
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file support for ARB_query_object
|
||||
*
|
||||
* ARB_query_object is implemented by using the PIPE_CONTROL command to stall
|
||||
* execution on the completion of previous depth tests, and write the
|
||||
* current PS_DEPTH_COUNT to a buffer object.
|
||||
*
|
||||
* We use before and after counts when drawing during a query so that
|
||||
* we don't pick up other clients' query data in ours. To reduce overhead,
|
||||
* a single BO is used to record the query data for all active queries at
|
||||
* once. This also gives us a simple bound on how much batchbuffer space is
|
||||
* required for handling queries, so that we can be sure that we won't
|
||||
* have to emit a batchbuffer without getting the ending PS_DEPTH_COUNT.
|
||||
*/
|
||||
#include "util/u_simple_list.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_reg.h"
|
||||
|
||||
/** Waits on the query object's BO and totals the results for this query */
|
||||
static boolean
|
||||
brw_query_get_result(struct pipe_context *pipe,
|
||||
struct pipe_query *q,
|
||||
boolean wait,
|
||||
uint64_t *result)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
struct brw_query_object *query = (struct brw_query_object *)q;
|
||||
|
||||
/* Map and count the pixels from the current query BO */
|
||||
if (query->bo) {
|
||||
int i;
|
||||
uint64_t *map;
|
||||
|
||||
if (brw->sws->bo_is_busy(query->bo) && !wait)
|
||||
return FALSE;
|
||||
|
||||
map = bo_map_read(brw->sws, query->bo);
|
||||
if (map == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (i = query->first_index; i <= query->last_index; i++) {
|
||||
query->result += map[i * 2 + 1] - map[i * 2];
|
||||
}
|
||||
|
||||
brw->sws->bo_unmap(query->bo);
|
||||
bo_reference(&query->bo, NULL);
|
||||
}
|
||||
|
||||
*result = query->result;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static struct pipe_query *
|
||||
brw_query_create(struct pipe_context *pipe, unsigned type )
|
||||
{
|
||||
struct brw_query_object *query;
|
||||
|
||||
switch (type) {
|
||||
case PIPE_QUERY_OCCLUSION_COUNTER:
|
||||
query = CALLOC_STRUCT( brw_query_object );
|
||||
if (query == NULL)
|
||||
return NULL;
|
||||
return (struct pipe_query *)query;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
brw_query_destroy(struct pipe_context *pipe, struct pipe_query *q)
|
||||
{
|
||||
struct brw_query_object *query = (struct brw_query_object *)q;
|
||||
|
||||
bo_reference(&query->bo, NULL);
|
||||
FREE(query);
|
||||
}
|
||||
|
||||
static void
|
||||
brw_query_begin(struct pipe_context *pipe, struct pipe_query *q)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
struct brw_query_object *query = (struct brw_query_object *)q;
|
||||
|
||||
/* Reset our driver's tracking of query state. */
|
||||
bo_reference(&query->bo, NULL);
|
||||
query->result = 0;
|
||||
query->first_index = -1;
|
||||
query->last_index = -1;
|
||||
|
||||
insert_at_head(&brw->query.active_head, query);
|
||||
brw->query.stats_wm++;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_QUERY;
|
||||
}
|
||||
|
||||
static void
|
||||
brw_query_end(struct pipe_context *pipe, struct pipe_query *q)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
struct brw_query_object *query = (struct brw_query_object *)q;
|
||||
|
||||
/* Flush the batchbuffer in case it has writes to our query BO.
|
||||
* Have later queries write to a new query BO so that further rendering
|
||||
* doesn't delay the collection of our results.
|
||||
*/
|
||||
if (query->bo) {
|
||||
brw_emit_query_end(brw);
|
||||
brw_context_flush( brw );
|
||||
|
||||
bo_reference(&brw->query.bo, NULL);
|
||||
}
|
||||
|
||||
remove_from_list(query);
|
||||
brw->query.stats_wm--;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_QUERY;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Internal functions and callbacks to implement queries
|
||||
*/
|
||||
|
||||
/** Called to set up the query BO and account for its aperture space */
|
||||
enum pipe_error
|
||||
brw_prepare_query_begin(struct brw_context *brw)
|
||||
{
|
||||
enum pipe_error ret;
|
||||
|
||||
/* Skip if we're not doing any queries. */
|
||||
if (is_empty_list(&brw->query.active_head))
|
||||
return PIPE_OK;
|
||||
|
||||
/* Get a new query BO if we're going to need it. */
|
||||
if (brw->query.bo == NULL ||
|
||||
brw->query.index * 2 + 1 >= 4096 / sizeof(uint64_t)) {
|
||||
|
||||
ret = brw->sws->bo_alloc(brw->sws, BRW_BUFFER_TYPE_QUERY, 4096, 1,
|
||||
&brw->query.bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
brw->query.index = 0;
|
||||
}
|
||||
|
||||
brw_add_validated_bo(brw, brw->query.bo);
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
/** Called just before primitive drawing to get a beginning PS_DEPTH_COUNT. */
|
||||
void
|
||||
brw_emit_query_begin(struct brw_context *brw)
|
||||
{
|
||||
struct brw_query_object *query;
|
||||
|
||||
/* Skip if we're not doing any queries, or we've emitted the start. */
|
||||
if (brw->query.active || is_empty_list(&brw->query.active_head))
|
||||
return;
|
||||
|
||||
BEGIN_BATCH(4, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH(_3DSTATE_PIPE_CONTROL |
|
||||
PIPE_CONTROL_DEPTH_STALL |
|
||||
PIPE_CONTROL_WRITE_DEPTH_COUNT);
|
||||
/* This object could be mapped cacheable, but we don't have an exposed
|
||||
* mechanism to support that. Since it's going uncached, tell GEM that
|
||||
* we're writing to it. The usual clflush should be all that's required
|
||||
* to pick up the results.
|
||||
*/
|
||||
OUT_RELOC(brw->query.bo,
|
||||
BRW_USAGE_QUERY_RESULT,
|
||||
PIPE_CONTROL_GLOBAL_GTT_WRITE |
|
||||
((brw->query.index * 2) * sizeof(uint64_t)));
|
||||
OUT_BATCH(0);
|
||||
OUT_BATCH(0);
|
||||
ADVANCE_BATCH();
|
||||
|
||||
foreach(query, &brw->query.active_head) {
|
||||
if (query->bo != brw->query.bo) {
|
||||
uint64_t tmp;
|
||||
|
||||
/* Propogate the results from this buffer to all of the
|
||||
* active queries, as the bo is going away.
|
||||
*/
|
||||
if (query->bo != NULL)
|
||||
brw_query_get_result( &brw->base,
|
||||
(struct pipe_query *)query,
|
||||
FALSE,
|
||||
&tmp );
|
||||
|
||||
bo_reference( &query->bo, brw->query.bo );
|
||||
query->first_index = brw->query.index;
|
||||
}
|
||||
query->last_index = brw->query.index;
|
||||
}
|
||||
brw->query.active = GL_TRUE;
|
||||
}
|
||||
|
||||
/** Called at batchbuffer flush to get an ending PS_DEPTH_COUNT */
|
||||
void
|
||||
brw_emit_query_end(struct brw_context *brw)
|
||||
{
|
||||
if (!brw->query.active)
|
||||
return;
|
||||
|
||||
BEGIN_BATCH(4, IGNORE_CLIPRECTS);
|
||||
OUT_BATCH(_3DSTATE_PIPE_CONTROL |
|
||||
PIPE_CONTROL_DEPTH_STALL |
|
||||
PIPE_CONTROL_WRITE_DEPTH_COUNT);
|
||||
OUT_RELOC(brw->query.bo,
|
||||
BRW_USAGE_QUERY_RESULT,
|
||||
PIPE_CONTROL_GLOBAL_GTT_WRITE |
|
||||
((brw->query.index * 2 + 1) * sizeof(uint64_t)));
|
||||
OUT_BATCH(0);
|
||||
OUT_BATCH(0);
|
||||
ADVANCE_BATCH();
|
||||
|
||||
brw->query.active = GL_FALSE;
|
||||
brw->query.index++;
|
||||
}
|
||||
|
||||
void brw_pipe_query_init( struct brw_context *brw )
|
||||
{
|
||||
brw->base.create_query = brw_query_create;
|
||||
brw->base.destroy_query = brw_query_destroy;
|
||||
brw->base.begin_query = brw_query_begin;
|
||||
brw->base.end_query = brw_query_end;
|
||||
brw->base.get_query_result = brw_query_get_result;
|
||||
}
|
||||
|
||||
|
||||
void brw_pipe_query_cleanup( struct brw_context *brw )
|
||||
{
|
||||
/* Unreference brw->query.bo ??
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_pipe_rast.h"
|
||||
#include "brw_wm.h"
|
||||
|
||||
|
||||
static unsigned translate_fill( unsigned fill )
|
||||
{
|
||||
switch (fill) {
|
||||
case PIPE_POLYGON_MODE_FILL:
|
||||
return CLIP_FILL;
|
||||
case PIPE_POLYGON_MODE_LINE:
|
||||
return CLIP_LINE;
|
||||
case PIPE_POLYGON_MODE_POINT:
|
||||
return CLIP_POINT;
|
||||
default:
|
||||
assert(0);
|
||||
return CLIP_FILL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Calculates the key for triangle-mode clipping. Non-triangle
|
||||
* clipping keys use much less information and are computed on the
|
||||
* fly.
|
||||
*/
|
||||
static void
|
||||
calculate_clip_key_rast( const struct brw_context *brw,
|
||||
const struct pipe_rasterizer_state *templ,
|
||||
const struct brw_rasterizer_state *rast,
|
||||
struct brw_clip_prog_key *key)
|
||||
{
|
||||
memset(key, 0, sizeof *key);
|
||||
|
||||
if (brw->chipset.is_igdng)
|
||||
key->clip_mode = BRW_CLIPMODE_KERNEL_CLIP;
|
||||
else
|
||||
key->clip_mode = BRW_CLIPMODE_NORMAL;
|
||||
|
||||
key->do_flat_shading = templ->flatshade;
|
||||
|
||||
if (templ->cull_mode == PIPE_WINDING_BOTH) {
|
||||
key->clip_mode = BRW_CLIPMODE_REJECT_ALL;
|
||||
return;
|
||||
}
|
||||
|
||||
key->fill_ccw = CLIP_CULL;
|
||||
key->fill_cw = CLIP_CULL;
|
||||
|
||||
if (!(templ->cull_mode & PIPE_WINDING_CCW)) {
|
||||
key->fill_ccw = translate_fill(templ->fill_ccw);
|
||||
}
|
||||
|
||||
if (!(templ->cull_mode & PIPE_WINDING_CW)) {
|
||||
key->fill_cw = translate_fill(templ->fill_cw);
|
||||
}
|
||||
|
||||
if (key->fill_cw == CLIP_LINE ||
|
||||
key->fill_ccw == CLIP_LINE ||
|
||||
key->fill_cw == CLIP_POINT ||
|
||||
key->fill_ccw == CLIP_POINT) {
|
||||
key->do_unfilled = 1;
|
||||
key->clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED;
|
||||
}
|
||||
|
||||
key->offset_ccw = templ->offset_ccw;
|
||||
key->offset_cw = templ->offset_cw;
|
||||
|
||||
if (templ->light_twoside && key->fill_cw != CLIP_CULL)
|
||||
key->copy_bfc_cw = 1;
|
||||
|
||||
if (templ->light_twoside && key->fill_ccw != CLIP_CULL)
|
||||
key->copy_bfc_ccw = 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calculate_line_stipple_rast( const struct pipe_rasterizer_state *templ,
|
||||
struct brw_line_stipple *bls )
|
||||
{
|
||||
GLfloat tmp = 1.0f / (templ->line_stipple_factor + 1);
|
||||
GLint tmpi = tmp * (1<<13);
|
||||
|
||||
bls->header.opcode = CMD_LINE_STIPPLE_PATTERN;
|
||||
bls->header.length = sizeof(*bls)/4 - 2;
|
||||
bls->bits0.pattern = templ->line_stipple_pattern;
|
||||
bls->bits1.repeat_count = templ->line_stipple_factor + 1;
|
||||
bls->bits1.inverse_repeat_count = tmpi;
|
||||
}
|
||||
|
||||
static void *brw_create_rasterizer_state( struct pipe_context *pipe,
|
||||
const struct pipe_rasterizer_state *templ )
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
struct brw_rasterizer_state *rast;
|
||||
|
||||
rast = CALLOC_STRUCT(brw_rasterizer_state);
|
||||
if (rast == NULL)
|
||||
return NULL;
|
||||
|
||||
rast->templ = *templ;
|
||||
|
||||
calculate_clip_key_rast( brw, templ, rast, &rast->clip_key );
|
||||
|
||||
if (templ->line_stipple_enable)
|
||||
calculate_line_stipple_rast( templ, &rast->bls );
|
||||
|
||||
/* Caclculate lookup value for WM IZ table.
|
||||
*/
|
||||
if (templ->line_smooth) {
|
||||
if (templ->fill_cw == PIPE_POLYGON_MODE_LINE &&
|
||||
templ->fill_ccw == PIPE_POLYGON_MODE_LINE) {
|
||||
rast->unfilled_aa_line = AA_ALWAYS;
|
||||
}
|
||||
else if (templ->fill_cw == PIPE_POLYGON_MODE_LINE ||
|
||||
templ->fill_ccw == PIPE_POLYGON_MODE_LINE) {
|
||||
rast->unfilled_aa_line = AA_SOMETIMES;
|
||||
}
|
||||
else {
|
||||
rast->unfilled_aa_line = AA_NEVER;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rast->unfilled_aa_line = AA_NEVER;
|
||||
}
|
||||
|
||||
return (void *)rast;
|
||||
}
|
||||
|
||||
|
||||
static void brw_bind_rasterizer_state(struct pipe_context *pipe,
|
||||
void *cso)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
brw->curr.rast = (const struct brw_rasterizer_state *)cso;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_RAST;
|
||||
}
|
||||
|
||||
static void brw_delete_rasterizer_state(struct pipe_context *pipe,
|
||||
void *cso)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
assert((const void *)cso != (const void *)brw->curr.rast);
|
||||
FREE(cso);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void brw_pipe_rast_init( struct brw_context *brw )
|
||||
{
|
||||
brw->base.create_rasterizer_state = brw_create_rasterizer_state;
|
||||
brw->base.bind_rasterizer_state = brw_bind_rasterizer_state;
|
||||
brw->base.delete_rasterizer_state = brw_delete_rasterizer_state;
|
||||
}
|
||||
|
||||
void brw_pipe_rast_cleanup( struct brw_context *brw )
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef BRW_PIPE_RAST_H
|
||||
#define BRW_PIPE_RAST_H
|
||||
|
||||
#include "brw_clip.h"
|
||||
|
||||
struct brw_rasterizer_state {
|
||||
struct pipe_rasterizer_state templ; /* for draw module */
|
||||
|
||||
/* Precalculated hardware state:
|
||||
*/
|
||||
struct brw_clip_prog_key clip_key;
|
||||
struct brw_line_stipple bls;
|
||||
unsigned unfilled_aa_line;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,233 @@
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_debug.h"
|
||||
|
||||
|
||||
|
||||
/* The brw (and related graphics cores) do not support GL_CLAMP. The
|
||||
* Intel drivers for "other operating systems" implement GL_CLAMP as
|
||||
* GL_CLAMP_TO_EDGE, so the same is done here.
|
||||
*/
|
||||
static GLuint translate_wrap_mode( unsigned wrap )
|
||||
{
|
||||
switch( wrap ) {
|
||||
case PIPE_TEX_WRAP_REPEAT:
|
||||
return BRW_TEXCOORDMODE_WRAP;
|
||||
|
||||
case PIPE_TEX_WRAP_CLAMP:
|
||||
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
|
||||
return BRW_TEXCOORDMODE_CLAMP;
|
||||
|
||||
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
|
||||
return BRW_TEXCOORDMODE_CLAMP_BORDER;
|
||||
|
||||
case PIPE_TEX_WRAP_MIRROR_REPEAT:
|
||||
return BRW_TEXCOORDMODE_MIRROR;
|
||||
|
||||
case PIPE_TEX_WRAP_MIRROR_CLAMP:
|
||||
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
|
||||
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
|
||||
return BRW_TEXCOORDMODE_MIRROR_ONCE;
|
||||
|
||||
default:
|
||||
return BRW_TEXCOORDMODE_WRAP;
|
||||
}
|
||||
}
|
||||
|
||||
static GLuint translate_img_filter( unsigned filter )
|
||||
{
|
||||
switch (filter) {
|
||||
case PIPE_TEX_FILTER_NEAREST:
|
||||
return BRW_MAPFILTER_NEAREST;
|
||||
case PIPE_TEX_FILTER_LINEAR:
|
||||
return BRW_MAPFILTER_LINEAR;
|
||||
case PIPE_TEX_FILTER_ANISO:
|
||||
return BRW_MAPFILTER_ANISOTROPIC;
|
||||
default:
|
||||
assert(0);
|
||||
return BRW_MAPFILTER_NEAREST;
|
||||
}
|
||||
}
|
||||
|
||||
static GLuint translate_mip_filter( unsigned filter )
|
||||
{
|
||||
switch (filter) {
|
||||
case PIPE_TEX_MIPFILTER_NONE:
|
||||
return BRW_MIPFILTER_NONE;
|
||||
case PIPE_TEX_MIPFILTER_NEAREST:
|
||||
return BRW_MIPFILTER_NEAREST;
|
||||
case PIPE_TEX_MIPFILTER_LINEAR:
|
||||
return BRW_MIPFILTER_LINEAR;
|
||||
default:
|
||||
assert(0);
|
||||
return BRW_MIPFILTER_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: not sure why there are special translations for the shadow tex
|
||||
* compare functions. In particular ALWAYS is translated to NEVER.
|
||||
* Is this a hardware issue? Does i965 really suffer from this?
|
||||
*/
|
||||
static GLuint translate_shadow_compare_func( unsigned func )
|
||||
{
|
||||
switch (func) {
|
||||
case PIPE_FUNC_NEVER:
|
||||
return BRW_COMPAREFUNCTION_ALWAYS;
|
||||
case PIPE_FUNC_LESS:
|
||||
return BRW_COMPAREFUNCTION_LEQUAL;
|
||||
case PIPE_FUNC_LEQUAL:
|
||||
return BRW_COMPAREFUNCTION_LESS;
|
||||
case PIPE_FUNC_GREATER:
|
||||
return BRW_COMPAREFUNCTION_GEQUAL;
|
||||
case PIPE_FUNC_GEQUAL:
|
||||
return BRW_COMPAREFUNCTION_GREATER;
|
||||
case PIPE_FUNC_NOTEQUAL:
|
||||
return BRW_COMPAREFUNCTION_EQUAL;
|
||||
case PIPE_FUNC_EQUAL:
|
||||
return BRW_COMPAREFUNCTION_NOTEQUAL;
|
||||
case PIPE_FUNC_ALWAYS:
|
||||
return BRW_COMPAREFUNCTION_NEVER;
|
||||
default:
|
||||
assert(0);
|
||||
return BRW_COMPAREFUNCTION_NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void *
|
||||
brw_create_sampler_state( struct pipe_context *pipe,
|
||||
const struct pipe_sampler_state *template )
|
||||
{
|
||||
struct brw_sampler *sampler = CALLOC_STRUCT(brw_sampler);
|
||||
|
||||
sampler->ss0.min_filter = translate_img_filter( template->min_img_filter );
|
||||
sampler->ss0.mag_filter = translate_img_filter( template->mag_img_filter );
|
||||
sampler->ss0.mip_filter = translate_mip_filter( template->min_mip_filter );
|
||||
|
||||
|
||||
/* XXX: anisotropy logic slightly changed:
|
||||
*/
|
||||
if (template->max_anisotropy > 1.0) {
|
||||
sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC;
|
||||
sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;
|
||||
|
||||
if (template->max_anisotropy > 2.0) {
|
||||
sampler->ss3.max_aniso = MIN2((template->max_anisotropy - 2) / 2,
|
||||
BRW_ANISORATIO_16);
|
||||
}
|
||||
}
|
||||
|
||||
sampler->ss1.r_wrap_mode = translate_wrap_mode(template->wrap_r);
|
||||
sampler->ss1.s_wrap_mode = translate_wrap_mode(template->wrap_s);
|
||||
sampler->ss1.t_wrap_mode = translate_wrap_mode(template->wrap_t);
|
||||
|
||||
/* Set LOD bias:
|
||||
*/
|
||||
sampler->ss0.lod_bias =
|
||||
util_signed_fixed(CLAMP(template->lod_bias, -16, 15), 6);
|
||||
|
||||
|
||||
sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
|
||||
sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */
|
||||
|
||||
/* Set shadow function:
|
||||
*/
|
||||
if (template->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
|
||||
|
||||
/* Shadowing is "enabled" by emitting a particular sampler
|
||||
* message (sample_c). So need to recompile WM program when
|
||||
* shadow comparison is enabled on each/any texture unit.
|
||||
*/
|
||||
sampler->ss0.shadow_function =
|
||||
translate_shadow_compare_func(template->compare_func);
|
||||
}
|
||||
|
||||
/* Set BaseMipLevel, MaxLOD, MinLOD:
|
||||
*/
|
||||
sampler->ss0.base_level =
|
||||
util_unsigned_fixed(0, 1);
|
||||
|
||||
sampler->ss1.max_lod =
|
||||
util_unsigned_fixed(CLAMP(template->max_lod, 0, 13), 6);
|
||||
|
||||
sampler->ss1.min_lod =
|
||||
util_unsigned_fixed(CLAMP(template->min_lod, 0, 13), 6);
|
||||
|
||||
return (void *)sampler;
|
||||
}
|
||||
|
||||
static void brw_bind_sampler_state(struct pipe_context *pipe,
|
||||
unsigned num, void **sampler)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
brw->curr.sampler[i] = sampler[i];
|
||||
|
||||
for (i = num; i < brw->curr.num_samplers; i++)
|
||||
brw->curr.sampler[i] = NULL;
|
||||
|
||||
brw->curr.num_samplers = num;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_SAMPLERS;
|
||||
}
|
||||
|
||||
static void brw_delete_sampler_state(struct pipe_context *pipe,
|
||||
void *cso)
|
||||
{
|
||||
FREE(cso);
|
||||
}
|
||||
|
||||
static void brw_set_sampler_textures(struct pipe_context *pipe,
|
||||
unsigned num,
|
||||
struct pipe_texture **texture)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
pipe_texture_reference(&brw->curr.texture[i], texture[i]);
|
||||
|
||||
for (i = num; i < brw->curr.num_textures; i++)
|
||||
pipe_texture_reference(&brw->curr.texture[i], NULL);
|
||||
|
||||
brw->curr.num_textures = num;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_BOUND_TEXTURES;
|
||||
}
|
||||
|
||||
static void brw_set_vertex_sampler_textures(struct pipe_context *pipe,
|
||||
unsigned num,
|
||||
struct pipe_texture **texture)
|
||||
{
|
||||
}
|
||||
|
||||
static void brw_bind_vertex_sampler_state(struct pipe_context *pipe,
|
||||
unsigned num, void **sampler)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void brw_pipe_sampler_init( struct brw_context *brw )
|
||||
{
|
||||
brw->base.create_sampler_state = brw_create_sampler_state;
|
||||
brw->base.delete_sampler_state = brw_delete_sampler_state;
|
||||
|
||||
brw->base.set_fragment_sampler_textures = brw_set_sampler_textures;
|
||||
brw->base.bind_fragment_sampler_states = brw_bind_sampler_state;
|
||||
|
||||
brw->base.set_vertex_sampler_textures = brw_set_vertex_sampler_textures;
|
||||
brw->base.bind_vertex_sampler_states = brw_bind_vertex_sampler_state;
|
||||
|
||||
}
|
||||
void brw_pipe_sampler_cleanup( struct brw_context *brw )
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "tgsi/tgsi_parse.h"
|
||||
#include "tgsi/tgsi_scan.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_wm.h"
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the given shader uses complex features such as flow
|
||||
* conditionals, loops, subroutines.
|
||||
*/
|
||||
static GLboolean has_flow_control(const struct tgsi_shader_info *info)
|
||||
{
|
||||
return (info->opcode_count[TGSI_OPCODE_ARL] > 0 ||
|
||||
info->opcode_count[TGSI_OPCODE_IF] > 0 ||
|
||||
info->opcode_count[TGSI_OPCODE_ENDIF] > 0 || /* redundant - IF */
|
||||
info->opcode_count[TGSI_OPCODE_CAL] > 0 ||
|
||||
info->opcode_count[TGSI_OPCODE_BRK] > 0 || /* redundant - BGNLOOP */
|
||||
info->opcode_count[TGSI_OPCODE_RET] > 0 || /* redundant - CAL */
|
||||
info->opcode_count[TGSI_OPCODE_BGNLOOP] > 0);
|
||||
}
|
||||
|
||||
|
||||
static void scan_immediates(const struct tgsi_token *tokens,
|
||||
const struct tgsi_shader_info *info,
|
||||
struct brw_immediate_data *imm)
|
||||
{
|
||||
struct tgsi_parse_context parse;
|
||||
boolean done = FALSE;
|
||||
|
||||
imm->nr = 0;
|
||||
imm->data = MALLOC(info->immediate_count * 4 * sizeof(float));
|
||||
|
||||
tgsi_parse_init( &parse, tokens );
|
||||
while (!tgsi_parse_end_of_tokens( &parse ) && !done) {
|
||||
tgsi_parse_token( &parse );
|
||||
|
||||
switch (parse.FullToken.Token.Type) {
|
||||
case TGSI_TOKEN_TYPE_DECLARATION:
|
||||
break;
|
||||
|
||||
case TGSI_TOKEN_TYPE_IMMEDIATE: {
|
||||
static const float id[4] = {0,0,0,1};
|
||||
const float *value = &parse.FullToken.FullImmediate.u[0].Float;
|
||||
unsigned size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
imm->data[imm->nr][i] = value[i];
|
||||
|
||||
for (; i < 4; i++)
|
||||
imm->data[imm->nr][i] = id[i];
|
||||
|
||||
imm->nr++;
|
||||
break;
|
||||
}
|
||||
|
||||
case TGSI_TOKEN_TYPE_INSTRUCTION:
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void brw_bind_fs_state( struct pipe_context *pipe, void *prog )
|
||||
{
|
||||
struct brw_fragment_shader *fs = (struct brw_fragment_shader *)prog;
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
|
||||
if (brw->curr.fragment_shader == fs)
|
||||
return;
|
||||
|
||||
if (brw->curr.fragment_shader == NULL ||
|
||||
fs == NULL ||
|
||||
memcmp(&brw->curr.fragment_shader->signature, &fs->signature,
|
||||
brw_fs_signature_size(&fs->signature)) != 0) {
|
||||
brw->state.dirty.mesa |= PIPE_NEW_FRAGMENT_SIGNATURE;
|
||||
}
|
||||
|
||||
brw->curr.fragment_shader = fs;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_FRAGMENT_SHADER;
|
||||
}
|
||||
|
||||
static void brw_bind_vs_state( struct pipe_context *pipe, void *prog )
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
|
||||
brw->curr.vertex_shader = (struct brw_vertex_shader *)prog;
|
||||
brw->state.dirty.mesa |= PIPE_NEW_VERTEX_SHADER;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void *brw_create_fs_state( struct pipe_context *pipe,
|
||||
const struct pipe_shader_state *shader )
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
struct brw_fragment_shader *fs;
|
||||
int i;
|
||||
|
||||
fs = CALLOC_STRUCT(brw_fragment_shader);
|
||||
if (fs == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Duplicate tokens, scan shader
|
||||
*/
|
||||
fs->id = brw->program_id++;
|
||||
fs->has_flow_control = has_flow_control(&fs->info);
|
||||
|
||||
fs->tokens = tgsi_dup_tokens(shader->tokens);
|
||||
if (fs->tokens == NULL)
|
||||
goto fail;
|
||||
|
||||
tgsi_scan_shader(fs->tokens, &fs->info);
|
||||
scan_immediates(fs->tokens, &fs->info, &fs->immediates);
|
||||
|
||||
fs->signature.nr_inputs = fs->info.num_inputs;
|
||||
for (i = 0; i < fs->info.num_inputs; i++) {
|
||||
fs->signature.input[i].interp = fs->info.input_interpolate[i];
|
||||
fs->signature.input[i].semantic = fs->info.input_semantic_name[i];
|
||||
fs->signature.input[i].semantic_index = fs->info.input_semantic_index[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < fs->info.num_inputs; i++)
|
||||
if (fs->info.input_semantic_name[i] == TGSI_SEMANTIC_POSITION)
|
||||
fs->uses_depth = 1;
|
||||
|
||||
if (fs->info.uses_kill)
|
||||
fs->iz_lookup |= IZ_PS_KILL_ALPHATEST_BIT;
|
||||
|
||||
if (fs->info.writes_z)
|
||||
fs->iz_lookup |= IZ_PS_COMPUTES_DEPTH_BIT;
|
||||
|
||||
return (void *)fs;
|
||||
|
||||
fail:
|
||||
FREE(fs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void *brw_create_vs_state( struct pipe_context *pipe,
|
||||
const struct pipe_shader_state *shader )
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
struct brw_vertex_shader *vs;
|
||||
unsigned i;
|
||||
|
||||
vs = CALLOC_STRUCT(brw_vertex_shader);
|
||||
if (vs == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Duplicate tokens, scan shader
|
||||
*/
|
||||
vs->tokens = tgsi_dup_tokens(shader->tokens);
|
||||
if (vs->tokens == NULL)
|
||||
goto fail;
|
||||
|
||||
tgsi_scan_shader(vs->tokens, &vs->info);
|
||||
scan_immediates(vs->tokens, &vs->info, &vs->immediates);
|
||||
|
||||
vs->id = brw->program_id++;
|
||||
vs->has_flow_control = has_flow_control(&vs->info);
|
||||
|
||||
for (i = 0; i < vs->info.num_outputs; i++) {
|
||||
int index = vs->info.output_semantic_index[i];
|
||||
switch (vs->info.output_semantic_name[i]) {
|
||||
case TGSI_SEMANTIC_POSITION:
|
||||
vs->output_hpos = i;
|
||||
break;
|
||||
case TGSI_SEMANTIC_COLOR:
|
||||
if (index == 0)
|
||||
vs->output_color0 = i;
|
||||
else
|
||||
vs->output_color1 = i;
|
||||
break;
|
||||
case TGSI_SEMANTIC_BCOLOR:
|
||||
if (index == 0)
|
||||
vs->output_bfc0 = i;
|
||||
else
|
||||
vs->output_bfc1 = i;
|
||||
break;
|
||||
#if 0
|
||||
case TGSI_SEMANTIC_EDGEFLAG:
|
||||
vs->output_edgeflag = i;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Done:
|
||||
*/
|
||||
return (void *)vs;
|
||||
|
||||
fail:
|
||||
FREE(vs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void brw_delete_fs_state( struct pipe_context *pipe, void *prog )
|
||||
{
|
||||
struct brw_fragment_shader *fs = (struct brw_fragment_shader *)prog;
|
||||
|
||||
bo_reference(&fs->const_buffer, NULL);
|
||||
FREE( (void *)fs->tokens );
|
||||
FREE( fs );
|
||||
}
|
||||
|
||||
|
||||
static void brw_delete_vs_state( struct pipe_context *pipe, void *prog )
|
||||
{
|
||||
struct brw_fragment_shader *vs = (struct brw_fragment_shader *)prog;
|
||||
|
||||
/* Delete draw shader
|
||||
*/
|
||||
FREE( (void *)vs->tokens );
|
||||
FREE( vs );
|
||||
}
|
||||
|
||||
|
||||
static void brw_set_constant_buffer(struct pipe_context *pipe,
|
||||
uint shader, uint index,
|
||||
const struct pipe_constant_buffer *buf)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
|
||||
assert(index == 0);
|
||||
|
||||
if (shader == PIPE_SHADER_FRAGMENT) {
|
||||
pipe_buffer_reference( &brw->curr.fragment_constants,
|
||||
buf->buffer );
|
||||
|
||||
brw->state.dirty.mesa |= PIPE_NEW_FRAGMENT_CONSTANTS;
|
||||
}
|
||||
else {
|
||||
pipe_buffer_reference( &brw->curr.vertex_constants,
|
||||
buf->buffer );
|
||||
|
||||
brw->state.dirty.mesa |= PIPE_NEW_VERTEX_CONSTANTS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void brw_pipe_shader_init( struct brw_context *brw )
|
||||
{
|
||||
brw->base.set_constant_buffer = brw_set_constant_buffer;
|
||||
|
||||
brw->base.create_vs_state = brw_create_vs_state;
|
||||
brw->base.bind_vs_state = brw_bind_vs_state;
|
||||
brw->base.delete_vs_state = brw_delete_vs_state;
|
||||
|
||||
brw->base.create_fs_state = brw_create_fs_state;
|
||||
brw->base.bind_fs_state = brw_bind_fs_state;
|
||||
brw->base.delete_fs_state = brw_delete_fs_state;
|
||||
}
|
||||
|
||||
void brw_pipe_shader_cleanup( struct brw_context *brw )
|
||||
{
|
||||
pipe_buffer_reference( &brw->curr.fragment_constants, NULL );
|
||||
pipe_buffer_reference( &brw->curr.vertex_constants, NULL );
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "brw_context.h"
|
||||
|
||||
|
||||
static void brw_set_vertex_elements( struct pipe_context *pipe,
|
||||
unsigned count,
|
||||
const struct pipe_vertex_element *elements )
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
|
||||
memcpy(brw->curr.vertex_element, elements, count * sizeof(elements[0]));
|
||||
brw->curr.num_vertex_elements = count;
|
||||
|
||||
brw->state.dirty.mesa |= PIPE_NEW_VERTEX_ELEMENT;
|
||||
}
|
||||
|
||||
|
||||
static void brw_set_vertex_buffers(struct pipe_context *pipe,
|
||||
unsigned count,
|
||||
const struct pipe_vertex_buffer *buffers)
|
||||
{
|
||||
struct brw_context *brw = brw_context(pipe);
|
||||
unsigned i;
|
||||
|
||||
/* Check for no change */
|
||||
if (count == brw->curr.num_vertex_buffers &&
|
||||
memcmp(brw->curr.vertex_buffer,
|
||||
buffers,
|
||||
count * sizeof buffers[0]) == 0)
|
||||
return;
|
||||
|
||||
/* Adjust refcounts */
|
||||
for (i = 0; i < count; i++)
|
||||
pipe_buffer_reference(&brw->curr.vertex_buffer[i].buffer,
|
||||
buffers[i].buffer);
|
||||
|
||||
for ( ; i < brw->curr.num_vertex_buffers; i++)
|
||||
pipe_buffer_reference(&brw->curr.vertex_buffer[i].buffer,
|
||||
NULL);
|
||||
|
||||
/* Copy remaining data */
|
||||
memcpy(brw->curr.vertex_buffer, buffers, count * sizeof buffers[0]);
|
||||
brw->curr.num_vertex_buffers = count;
|
||||
|
||||
brw->state.dirty.mesa |= PIPE_NEW_VERTEX_BUFFER;
|
||||
}
|
||||
|
||||
static void brw_set_edgeflags( struct pipe_context *pipe,
|
||||
const unsigned *bitfield )
|
||||
{
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
brw_pipe_vertex_init( struct brw_context *brw )
|
||||
{
|
||||
brw->base.set_vertex_buffers = brw_set_vertex_buffers;
|
||||
brw->base.set_vertex_elements = brw_set_vertex_elements;
|
||||
brw->base.set_edgeflags = brw_set_edgeflags;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
brw_pipe_vertex_cleanup( struct brw_context *brw )
|
||||
{
|
||||
|
||||
/* Release bound pipe vertex_buffers
|
||||
*/
|
||||
|
||||
/* Release some other stuff
|
||||
*/
|
||||
#if 0
|
||||
for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
|
||||
bo_reference(&brw->vb.inputs[i].bo, NULL);
|
||||
brw->vb.inputs[i].bo = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef BRW_REG_H
|
||||
#define BRW_REG_H
|
||||
|
||||
#define CMD_MI (0x0 << 29)
|
||||
#define CMD_2D (0x2 << 29)
|
||||
#define CMD_3D (0x3 << 29)
|
||||
|
||||
#define MI_NOOP (CMD_MI | 0)
|
||||
#define MI_BATCH_BUFFER_END (CMD_MI | 0xA << 23)
|
||||
#define MI_FLUSH (CMD_MI | (4 << 23))
|
||||
|
||||
#define _3DSTATE_DRAWRECT_INFO_I965 (CMD_3D | (3 << 27) | (1 << 24) | 0x2)
|
||||
|
||||
/** @{
|
||||
*
|
||||
* PIPE_CONTROL operation, a combination MI_FLUSH and register write with
|
||||
* additional flushing control.
|
||||
*/
|
||||
#define _3DSTATE_PIPE_CONTROL (CMD_3D | (3 << 27) | (2 << 24) | 2)
|
||||
#define PIPE_CONTROL_NO_WRITE (0 << 14)
|
||||
#define PIPE_CONTROL_WRITE_IMMEDIATE (1 << 14)
|
||||
#define PIPE_CONTROL_WRITE_DEPTH_COUNT (2 << 14)
|
||||
#define PIPE_CONTROL_WRITE_TIMESTAMP (3 << 14)
|
||||
#define PIPE_CONTROL_DEPTH_STALL (1 << 13)
|
||||
#define PIPE_CONTROL_WRITE_FLUSH (1 << 12)
|
||||
#define PIPE_CONTROL_INSTRUCTION_FLUSH (1 << 11)
|
||||
#define PIPE_CONTROL_INTERRUPT_ENABLE (1 << 8)
|
||||
#define PIPE_CONTROL_PPGTT_WRITE (0 << 2)
|
||||
#define PIPE_CONTROL_GLOBAL_GTT_WRITE (1 << 2)
|
||||
|
||||
/** @} */
|
||||
|
||||
#define XY_SETUP_BLT_CMD (CMD_2D | (0x01 << 22) | 6)
|
||||
#define XY_COLOR_BLT_CMD (CMD_2D | (0x50 << 22) | 4)
|
||||
#define XY_SRC_COPY_BLT_CMD (CMD_2D | (0x53 << 22) | 6)
|
||||
|
||||
/* BR00 */
|
||||
#define XY_BLT_WRITE_ALPHA (1 << 21)
|
||||
#define XY_BLT_WRITE_RGB (1 << 20)
|
||||
#define XY_SRC_TILED (1 << 15)
|
||||
#define XY_DST_TILED (1 << 11)
|
||||
|
||||
/* BR13 */
|
||||
#define BR13_565 (0x1 << 24)
|
||||
#define BR13_8888 (0x3 << 24)
|
||||
|
||||
#define FENCE_LINEAR 0
|
||||
#define FENCE_XMAJOR 1
|
||||
#define FENCE_YMAJOR 2
|
||||
|
||||
|
||||
|
||||
/* PCI IDs
|
||||
*/
|
||||
#define PCI_CHIP_I965_G 0x29A2
|
||||
#define PCI_CHIP_I965_Q 0x2992
|
||||
#define PCI_CHIP_I965_G_1 0x2982
|
||||
#define PCI_CHIP_I946_GZ 0x2972
|
||||
#define PCI_CHIP_I965_GM 0x2A02
|
||||
#define PCI_CHIP_I965_GME 0x2A12
|
||||
|
||||
#define PCI_CHIP_GM45_GM 0x2A42
|
||||
|
||||
#define PCI_CHIP_IGD_E_G 0x2E02
|
||||
#define PCI_CHIP_Q45_G 0x2E12
|
||||
#define PCI_CHIP_G45_G 0x2E22
|
||||
#define PCI_CHIP_G41_G 0x2E32
|
||||
#define PCI_CHIP_B43_G 0x2E42
|
||||
|
||||
#define PCI_CHIP_ILD_G 0x0042
|
||||
#define PCI_CHIP_ILM_G 0x0046
|
||||
|
||||
struct brw_chipset {
|
||||
unsigned pci_id:16;
|
||||
unsigned is_965:1;
|
||||
unsigned is_igdng:1;
|
||||
unsigned is_g4x:1;
|
||||
unsigned pad:13;
|
||||
};
|
||||
|
||||
|
||||
/* XXX: hacks
|
||||
*/
|
||||
#define VERT_RESULT_HPOS 0 /* not always true */
|
||||
#define VERT_RESULT_PSIZ 10000 /* disabled */
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,403 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 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 "pipe/p_inlines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_string.h"
|
||||
|
||||
#include "brw_reg.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_screen.h"
|
||||
#include "brw_winsys.h"
|
||||
#include "brw_debug.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
static const struct debug_named_value debug_names[] = {
|
||||
{ "tex", DEBUG_TEXTURE},
|
||||
{ "state", DEBUG_STATE},
|
||||
{ "ioctl", DEBUG_IOCTL},
|
||||
{ "blit", DEBUG_BLIT},
|
||||
{ "curbe", DEBUG_CURBE},
|
||||
{ "fall", DEBUG_FALLBACKS},
|
||||
{ "verb", DEBUG_VERBOSE},
|
||||
{ "bat", DEBUG_BATCH},
|
||||
{ "pix", DEBUG_PIXEL},
|
||||
{ "wins", DEBUG_WINSYS},
|
||||
{ "min", DEBUG_MIN_URB},
|
||||
{ "dis", DEBUG_DISASSEM},
|
||||
{ "sync", DEBUG_SYNC},
|
||||
{ "prim", DEBUG_PRIMS },
|
||||
{ "vert", DEBUG_VERTS },
|
||||
{ "dma", DEBUG_DMA },
|
||||
{ "san", DEBUG_SANITY },
|
||||
{ "sleep", DEBUG_SLEEP },
|
||||
{ "stats", DEBUG_STATS },
|
||||
{ "sing", DEBUG_SINGLE_THREAD },
|
||||
{ "thre", DEBUG_SINGLE_THREAD },
|
||||
{ "wm", DEBUG_WM },
|
||||
{ "urb", DEBUG_URB },
|
||||
{ "vs", DEBUG_VS },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static const struct debug_named_value dump_names[] = {
|
||||
{ "asm", DUMP_ASM},
|
||||
{ "state", DUMP_STATE},
|
||||
{ "batch", DUMP_BATCH},
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
int BRW_DEBUG = 0;
|
||||
int BRW_DUMP = 0;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Probe functions
|
||||
*/
|
||||
|
||||
|
||||
static const char *
|
||||
brw_get_vendor(struct pipe_screen *screen)
|
||||
{
|
||||
return "VMware, Inc.";
|
||||
}
|
||||
|
||||
static const char *
|
||||
brw_get_name(struct pipe_screen *screen)
|
||||
{
|
||||
static char buffer[128];
|
||||
const char *chipset;
|
||||
|
||||
switch (brw_screen(screen)->chipset.pci_id) {
|
||||
case PCI_CHIP_I965_G:
|
||||
chipset = "I965_G";
|
||||
break;
|
||||
case PCI_CHIP_I965_Q:
|
||||
chipset = "I965_Q";
|
||||
break;
|
||||
case PCI_CHIP_I965_G_1:
|
||||
chipset = "I965_G_1";
|
||||
break;
|
||||
case PCI_CHIP_I946_GZ:
|
||||
chipset = "I946_GZ";
|
||||
break;
|
||||
case PCI_CHIP_I965_GM:
|
||||
chipset = "I965_GM";
|
||||
break;
|
||||
case PCI_CHIP_I965_GME:
|
||||
chipset = "I965_GME";
|
||||
break;
|
||||
case PCI_CHIP_GM45_GM:
|
||||
chipset = "GM45_GM";
|
||||
break;
|
||||
case PCI_CHIP_IGD_E_G:
|
||||
chipset = "IGD_E_G";
|
||||
break;
|
||||
case PCI_CHIP_Q45_G:
|
||||
chipset = "Q45_G";
|
||||
break;
|
||||
case PCI_CHIP_G45_G:
|
||||
chipset = "G45_G";
|
||||
break;
|
||||
case PCI_CHIP_G41_G:
|
||||
chipset = "G41_G";
|
||||
break;
|
||||
case PCI_CHIP_B43_G:
|
||||
chipset = "B43_G";
|
||||
break;
|
||||
case PCI_CHIP_ILD_G:
|
||||
chipset = "ILD_G";
|
||||
break;
|
||||
case PCI_CHIP_ILM_G:
|
||||
chipset = "ILM_G";
|
||||
break;
|
||||
}
|
||||
|
||||
util_snprintf(buffer, sizeof(buffer), "i965 (chipset: %s)", chipset);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int
|
||||
brw_get_param(struct pipe_screen *screen, int param)
|
||||
{
|
||||
switch (param) {
|
||||
case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
|
||||
return 8;
|
||||
case PIPE_CAP_NPOT_TEXTURES:
|
||||
return 1;
|
||||
case PIPE_CAP_TWO_SIDED_STENCIL:
|
||||
return 1;
|
||||
case PIPE_CAP_GLSL:
|
||||
return 0;
|
||||
case PIPE_CAP_ANISOTROPIC_FILTER:
|
||||
return 0;
|
||||
case PIPE_CAP_POINT_SPRITE:
|
||||
return 0;
|
||||
case PIPE_CAP_MAX_RENDER_TARGETS:
|
||||
return 1;
|
||||
case PIPE_CAP_OCCLUSION_QUERY:
|
||||
return 0;
|
||||
case PIPE_CAP_TEXTURE_SHADOW_MAP:
|
||||
return 1;
|
||||
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
|
||||
return 11; /* max 1024x1024 */
|
||||
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
|
||||
return 8; /* max 128x128x128 */
|
||||
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
|
||||
return 11; /* max 1024x1024 */
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static float
|
||||
brw_get_paramf(struct pipe_screen *screen, int param)
|
||||
{
|
||||
switch (param) {
|
||||
case PIPE_CAP_MAX_LINE_WIDTH:
|
||||
/* fall-through */
|
||||
case PIPE_CAP_MAX_LINE_WIDTH_AA:
|
||||
return 7.5;
|
||||
|
||||
case PIPE_CAP_MAX_POINT_WIDTH:
|
||||
/* fall-through */
|
||||
case PIPE_CAP_MAX_POINT_WIDTH_AA:
|
||||
return 255.0;
|
||||
|
||||
case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
|
||||
return 4.0;
|
||||
|
||||
case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
|
||||
return 16.0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean
|
||||
brw_is_format_supported(struct pipe_screen *screen,
|
||||
enum pipe_format format,
|
||||
enum pipe_texture_target target,
|
||||
unsigned tex_usage,
|
||||
unsigned geom_flags)
|
||||
{
|
||||
static const enum pipe_format tex_supported[] = {
|
||||
PIPE_FORMAT_L8_UNORM,
|
||||
PIPE_FORMAT_I8_UNORM,
|
||||
PIPE_FORMAT_A8_UNORM,
|
||||
PIPE_FORMAT_L16_UNORM,
|
||||
/*PIPE_FORMAT_I16_UNORM,*/
|
||||
/*PIPE_FORMAT_A16_UNORM,*/
|
||||
PIPE_FORMAT_A8L8_UNORM,
|
||||
PIPE_FORMAT_R5G6B5_UNORM,
|
||||
PIPE_FORMAT_A1R5G5B5_UNORM,
|
||||
PIPE_FORMAT_A4R4G4B4_UNORM,
|
||||
PIPE_FORMAT_X8R8G8B8_UNORM,
|
||||
PIPE_FORMAT_A8R8G8B8_UNORM,
|
||||
/* video */
|
||||
PIPE_FORMAT_YCBCR,
|
||||
PIPE_FORMAT_YCBCR_REV,
|
||||
/* compressed */
|
||||
/*PIPE_FORMAT_FXT1_RGBA,*/
|
||||
PIPE_FORMAT_DXT1_RGB,
|
||||
PIPE_FORMAT_DXT1_RGBA,
|
||||
PIPE_FORMAT_DXT3_RGBA,
|
||||
PIPE_FORMAT_DXT5_RGBA,
|
||||
/* sRGB */
|
||||
PIPE_FORMAT_R8G8B8A8_SRGB,
|
||||
PIPE_FORMAT_A8L8_SRGB,
|
||||
PIPE_FORMAT_L8_SRGB,
|
||||
PIPE_FORMAT_DXT1_SRGB,
|
||||
/* depth */
|
||||
PIPE_FORMAT_Z32_FLOAT,
|
||||
PIPE_FORMAT_X8Z24_UNORM,
|
||||
PIPE_FORMAT_S8Z24_UNORM,
|
||||
PIPE_FORMAT_Z16_UNORM,
|
||||
/* signed */
|
||||
PIPE_FORMAT_R8G8_SNORM,
|
||||
PIPE_FORMAT_R8G8B8A8_SNORM,
|
||||
PIPE_FORMAT_NONE /* list terminator */
|
||||
};
|
||||
static const enum pipe_format render_supported[] = {
|
||||
PIPE_FORMAT_X8R8G8B8_UNORM,
|
||||
PIPE_FORMAT_A8R8G8B8_UNORM,
|
||||
PIPE_FORMAT_R5G6B5_UNORM,
|
||||
PIPE_FORMAT_NONE /* list terminator */
|
||||
};
|
||||
static const enum pipe_format depth_supported[] = {
|
||||
PIPE_FORMAT_Z32_FLOAT,
|
||||
PIPE_FORMAT_X8Z24_UNORM,
|
||||
PIPE_FORMAT_S8Z24_UNORM,
|
||||
PIPE_FORMAT_Z16_UNORM,
|
||||
PIPE_FORMAT_NONE /* list terminator */
|
||||
};
|
||||
const enum pipe_format *list;
|
||||
uint i;
|
||||
|
||||
if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL)
|
||||
list = depth_supported;
|
||||
else if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET)
|
||||
list = render_supported;
|
||||
else
|
||||
list = tex_supported;
|
||||
|
||||
for (i = 0; list[i] != PIPE_FORMAT_NONE; i++) {
|
||||
if (list[i] == format)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fence functions
|
||||
*/
|
||||
|
||||
|
||||
static void
|
||||
brw_fence_reference(struct pipe_screen *screen,
|
||||
struct pipe_fence_handle **ptr,
|
||||
struct pipe_fence_handle *fence)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
brw_fence_signalled(struct pipe_screen *screen,
|
||||
struct pipe_fence_handle *fence,
|
||||
unsigned flags)
|
||||
{
|
||||
return 0; /* XXX shouldn't this be a boolean? */
|
||||
}
|
||||
|
||||
static int
|
||||
brw_fence_finish(struct pipe_screen *screen,
|
||||
struct pipe_fence_handle *fence,
|
||||
unsigned flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generic functions
|
||||
*/
|
||||
|
||||
|
||||
static void
|
||||
brw_destroy_screen(struct pipe_screen *screen)
|
||||
{
|
||||
struct brw_screen *bscreen = brw_screen(screen);
|
||||
|
||||
if (bscreen->sws)
|
||||
bscreen->sws->destroy(bscreen->sws);
|
||||
|
||||
FREE(bscreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new brw_screen object
|
||||
*/
|
||||
struct pipe_screen *
|
||||
brw_create_screen(struct brw_winsys_screen *sws, uint pci_id)
|
||||
{
|
||||
struct brw_screen *bscreen;
|
||||
struct brw_chipset chipset;
|
||||
|
||||
#ifdef DEBUG
|
||||
BRW_DEBUG = debug_get_flags_option("BRW_DEBUG", debug_names, 0);
|
||||
BRW_DEBUG |= debug_get_flags_option("INTEL_DEBUG", debug_names, 0);
|
||||
BRW_DEBUG |= DEBUG_STATS | DEBUG_MIN_URB | DEBUG_WM;
|
||||
|
||||
BRW_DUMP = debug_get_flags_option("BRW_DUMP", dump_names, 0);
|
||||
#endif
|
||||
|
||||
memset(&chipset, 0, sizeof chipset);
|
||||
|
||||
chipset.pci_id = pci_id;
|
||||
|
||||
switch (pci_id) {
|
||||
case PCI_CHIP_I965_G:
|
||||
case PCI_CHIP_I965_Q:
|
||||
case PCI_CHIP_I965_G_1:
|
||||
case PCI_CHIP_I946_GZ:
|
||||
case PCI_CHIP_I965_GM:
|
||||
case PCI_CHIP_I965_GME:
|
||||
chipset.is_965 = TRUE;
|
||||
break;
|
||||
|
||||
case PCI_CHIP_GM45_GM:
|
||||
case PCI_CHIP_IGD_E_G:
|
||||
case PCI_CHIP_Q45_G:
|
||||
case PCI_CHIP_G45_G:
|
||||
case PCI_CHIP_G41_G:
|
||||
case PCI_CHIP_B43_G:
|
||||
chipset.is_g4x = TRUE;
|
||||
break;
|
||||
|
||||
case PCI_CHIP_ILD_G:
|
||||
case PCI_CHIP_ILM_G:
|
||||
chipset.is_igdng = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug_printf("%s: unknown pci id 0x%x, cannot create screen\n",
|
||||
__FUNCTION__, pci_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bscreen = CALLOC_STRUCT(brw_screen);
|
||||
if (!bscreen)
|
||||
return NULL;
|
||||
|
||||
bscreen->chipset = chipset;
|
||||
bscreen->sws = sws;
|
||||
bscreen->base.winsys = NULL;
|
||||
bscreen->base.destroy = brw_destroy_screen;
|
||||
bscreen->base.get_name = brw_get_name;
|
||||
bscreen->base.get_vendor = brw_get_vendor;
|
||||
bscreen->base.get_param = brw_get_param;
|
||||
bscreen->base.get_paramf = brw_get_paramf;
|
||||
bscreen->base.is_format_supported = brw_is_format_supported;
|
||||
bscreen->base.fence_reference = brw_fence_reference;
|
||||
bscreen->base.fence_signalled = brw_fence_signalled;
|
||||
bscreen->base.fence_finish = brw_fence_finish;
|
||||
|
||||
brw_screen_tex_init(bscreen);
|
||||
brw_screen_tex_surface_init(bscreen);
|
||||
brw_screen_buffer_init(bscreen);
|
||||
|
||||
bscreen->no_tiling = debug_get_option("BRW_NO_TILING", FALSE) != NULL;
|
||||
|
||||
|
||||
return &bscreen->base;
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef BRW_SCREEN_H
|
||||
#define BRW_SCREEN_H
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
#include "pipe/p_screen.h"
|
||||
|
||||
#include "brw_reg.h"
|
||||
#include "brw_structs.h"
|
||||
|
||||
struct brw_winsys_screen;
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of pipe_screen
|
||||
*/
|
||||
struct brw_screen
|
||||
{
|
||||
struct pipe_screen base;
|
||||
struct brw_chipset chipset;
|
||||
struct brw_winsys_screen *sws;
|
||||
boolean no_tiling;
|
||||
};
|
||||
|
||||
/**
|
||||
* Subclass of pipe_transfer
|
||||
*/
|
||||
struct brw_transfer
|
||||
{
|
||||
struct pipe_transfer base;
|
||||
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
struct brw_buffer
|
||||
{
|
||||
struct pipe_buffer base;
|
||||
|
||||
/* One of either bo or user_buffer will be non-null, depending on
|
||||
* whether this is a hardware or user buffer.
|
||||
*/
|
||||
struct brw_winsys_buffer *bo;
|
||||
void *user_buffer;
|
||||
|
||||
/* Mapped pointer??
|
||||
*/
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
|
||||
union brw_surface_id {
|
||||
struct {
|
||||
unsigned face:3;
|
||||
unsigned zslice:13;
|
||||
unsigned level:16;
|
||||
} bits;
|
||||
unsigned value;
|
||||
};
|
||||
|
||||
|
||||
struct brw_surface
|
||||
{
|
||||
struct pipe_surface base;
|
||||
|
||||
union brw_surface_id id;
|
||||
unsigned cpp;
|
||||
unsigned pitch;
|
||||
unsigned draw_offset;
|
||||
unsigned tiling;
|
||||
|
||||
struct brw_surface_state ss;
|
||||
struct brw_winsys_buffer *bo;
|
||||
struct brw_surface *next, *prev;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct brw_texture
|
||||
{
|
||||
struct pipe_texture base;
|
||||
struct brw_winsys_buffer *bo;
|
||||
struct brw_surface_state ss;
|
||||
|
||||
unsigned *image_offset[PIPE_MAX_TEXTURE_LEVELS];
|
||||
unsigned nr_images[PIPE_MAX_TEXTURE_LEVELS];
|
||||
unsigned level_offset[PIPE_MAX_TEXTURE_LEVELS];
|
||||
|
||||
boolean compressed;
|
||||
unsigned brw_target;
|
||||
unsigned pitch;
|
||||
unsigned tiling;
|
||||
unsigned cpp;
|
||||
unsigned total_height;
|
||||
|
||||
struct brw_surface views[2];
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Cast wrappers
|
||||
*/
|
||||
static INLINE struct brw_screen *
|
||||
brw_screen(struct pipe_screen *pscreen)
|
||||
{
|
||||
return (struct brw_screen *) pscreen;
|
||||
}
|
||||
|
||||
static INLINE struct brw_transfer *
|
||||
brw_transfer(struct pipe_transfer *transfer)
|
||||
{
|
||||
return (struct brw_transfer *)transfer;
|
||||
}
|
||||
|
||||
static INLINE struct brw_surface *
|
||||
brw_surface(struct pipe_surface *surface)
|
||||
{
|
||||
return (struct brw_surface *)surface;
|
||||
}
|
||||
|
||||
static INLINE struct brw_buffer *
|
||||
brw_buffer(struct pipe_buffer *buffer)
|
||||
{
|
||||
return (struct brw_buffer *)buffer;
|
||||
}
|
||||
|
||||
static INLINE struct brw_texture *
|
||||
brw_texture(struct pipe_texture *texture)
|
||||
{
|
||||
return (struct brw_texture *)texture;
|
||||
}
|
||||
|
||||
|
||||
/* Pipe buffer helpers
|
||||
*/
|
||||
static INLINE boolean
|
||||
brw_buffer_is_user_buffer( const struct pipe_buffer *buf )
|
||||
{
|
||||
return ((const struct brw_buffer *)buf)->user_buffer != NULL;
|
||||
}
|
||||
|
||||
unsigned
|
||||
brw_surface_pitch( const struct pipe_surface *surface );
|
||||
|
||||
/***********************************************************************
|
||||
* Internal functions
|
||||
*/
|
||||
GLboolean brw_texture_layout(struct brw_screen *brw_screen,
|
||||
struct brw_texture *tex );
|
||||
|
||||
void brw_update_texture( struct brw_screen *brw_screen,
|
||||
struct brw_texture *tex );
|
||||
|
||||
|
||||
void brw_screen_tex_init( struct brw_screen *brw_screen );
|
||||
void brw_screen_tex_surface_init( struct brw_screen *brw_screen );
|
||||
|
||||
void brw_screen_buffer_init(struct brw_screen *brw_screen);
|
||||
|
||||
|
||||
boolean brw_is_texture_referenced_by_bo( struct brw_screen *brw_screen,
|
||||
struct pipe_texture *texture,
|
||||
unsigned face,
|
||||
unsigned level,
|
||||
struct brw_winsys_buffer *bo );
|
||||
|
||||
boolean brw_is_buffer_referenced_by_bo( struct brw_screen *brw_screen,
|
||||
struct pipe_buffer *buffer,
|
||||
struct brw_winsys_buffer *bo );
|
||||
|
||||
|
||||
|
||||
#endif /* BRW_SCREEN_H */
|
||||
@@ -0,0 +1,202 @@
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_inlines.h"
|
||||
|
||||
#include "brw_screen.h"
|
||||
#include "brw_winsys.h"
|
||||
|
||||
|
||||
|
||||
static void *
|
||||
brw_buffer_map_range( struct pipe_screen *screen,
|
||||
struct pipe_buffer *buffer,
|
||||
unsigned offset,
|
||||
unsigned length,
|
||||
unsigned usage )
|
||||
{
|
||||
struct brw_screen *bscreen = brw_screen(screen);
|
||||
struct brw_winsys_screen *sws = bscreen->sws;
|
||||
struct brw_buffer *buf = brw_buffer( buffer );
|
||||
|
||||
if (buf->user_buffer)
|
||||
return buf->user_buffer;
|
||||
|
||||
return sws->bo_map( buf->bo,
|
||||
BRW_DATA_OTHER,
|
||||
offset,
|
||||
length,
|
||||
(usage & PIPE_BUFFER_USAGE_CPU_WRITE) ? TRUE : FALSE,
|
||||
(usage & PIPE_BUFFER_USAGE_DISCARD) ? TRUE : FALSE,
|
||||
(usage & PIPE_BUFFER_USAGE_FLUSH_EXPLICIT) ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
static void *
|
||||
brw_buffer_map( struct pipe_screen *screen,
|
||||
struct pipe_buffer *buffer,
|
||||
unsigned usage )
|
||||
{
|
||||
struct brw_screen *bscreen = brw_screen(screen);
|
||||
struct brw_winsys_screen *sws = bscreen->sws;
|
||||
struct brw_buffer *buf = brw_buffer( buffer );
|
||||
|
||||
if (buf->user_buffer)
|
||||
return buf->user_buffer;
|
||||
|
||||
return sws->bo_map( buf->bo,
|
||||
BRW_DATA_OTHER,
|
||||
0,
|
||||
buf->base.size,
|
||||
(usage & PIPE_BUFFER_USAGE_CPU_WRITE) ? TRUE : FALSE,
|
||||
FALSE,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brw_buffer_flush_mapped_range( struct pipe_screen *screen,
|
||||
struct pipe_buffer *buffer,
|
||||
unsigned offset,
|
||||
unsigned length )
|
||||
{
|
||||
struct brw_screen *bscreen = brw_screen(screen);
|
||||
struct brw_winsys_screen *sws = bscreen->sws;
|
||||
struct brw_buffer *buf = brw_buffer( buffer );
|
||||
|
||||
if (buf->user_buffer)
|
||||
return;
|
||||
|
||||
sws->bo_flush_range( buf->bo,
|
||||
offset,
|
||||
length );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brw_buffer_unmap( struct pipe_screen *screen,
|
||||
struct pipe_buffer *buffer )
|
||||
{
|
||||
struct brw_screen *bscreen = brw_screen(screen);
|
||||
struct brw_winsys_screen *sws = bscreen->sws;
|
||||
struct brw_buffer *buf = brw_buffer( buffer );
|
||||
|
||||
if (buf->bo)
|
||||
sws->bo_unmap(buf->bo);
|
||||
}
|
||||
|
||||
static void
|
||||
brw_buffer_destroy( struct pipe_buffer *buffer )
|
||||
{
|
||||
struct brw_buffer *buf = brw_buffer( buffer );
|
||||
|
||||
assert(!p_atomic_read(&buffer->reference.count));
|
||||
|
||||
bo_reference(&buf->bo, NULL);
|
||||
FREE(buf);
|
||||
}
|
||||
|
||||
|
||||
static struct pipe_buffer *
|
||||
brw_buffer_create(struct pipe_screen *screen,
|
||||
unsigned alignment,
|
||||
unsigned usage,
|
||||
unsigned size)
|
||||
{
|
||||
struct brw_screen *bscreen = brw_screen(screen);
|
||||
struct brw_winsys_screen *sws = bscreen->sws;
|
||||
struct brw_buffer *buf;
|
||||
unsigned buffer_type;
|
||||
enum pipe_error ret;
|
||||
|
||||
buf = CALLOC_STRUCT(brw_buffer);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
pipe_reference_init(&buf->base.reference, 1);
|
||||
buf->base.screen = screen;
|
||||
buf->base.alignment = alignment;
|
||||
buf->base.usage = usage;
|
||||
buf->base.size = size;
|
||||
|
||||
switch (usage & (PIPE_BUFFER_USAGE_VERTEX |
|
||||
PIPE_BUFFER_USAGE_INDEX |
|
||||
PIPE_BUFFER_USAGE_PIXEL |
|
||||
PIPE_BUFFER_USAGE_CONSTANT))
|
||||
{
|
||||
case PIPE_BUFFER_USAGE_VERTEX:
|
||||
case PIPE_BUFFER_USAGE_INDEX:
|
||||
case (PIPE_BUFFER_USAGE_VERTEX|PIPE_BUFFER_USAGE_INDEX):
|
||||
buffer_type = BRW_BUFFER_TYPE_VERTEX;
|
||||
break;
|
||||
|
||||
case PIPE_BUFFER_USAGE_PIXEL:
|
||||
buffer_type = BRW_BUFFER_TYPE_PIXEL;
|
||||
break;
|
||||
|
||||
case PIPE_BUFFER_USAGE_CONSTANT:
|
||||
buffer_type = BRW_BUFFER_TYPE_SHADER_CONSTANTS;
|
||||
break;
|
||||
|
||||
default:
|
||||
buffer_type = BRW_BUFFER_TYPE_GENERIC;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = sws->bo_alloc( sws, buffer_type,
|
||||
size, alignment,
|
||||
&buf->bo );
|
||||
if (ret != PIPE_OK)
|
||||
return NULL;
|
||||
|
||||
return &buf->base;
|
||||
}
|
||||
|
||||
|
||||
static struct pipe_buffer *
|
||||
brw_user_buffer_create(struct pipe_screen *screen,
|
||||
void *ptr,
|
||||
unsigned bytes)
|
||||
{
|
||||
struct brw_buffer *buf;
|
||||
|
||||
buf = CALLOC_STRUCT(brw_buffer);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
buf->user_buffer = ptr;
|
||||
|
||||
pipe_reference_init(&buf->base.reference, 1);
|
||||
buf->base.screen = screen;
|
||||
buf->base.alignment = 1;
|
||||
buf->base.usage = 0;
|
||||
buf->base.size = bytes;
|
||||
|
||||
return &buf->base;
|
||||
}
|
||||
|
||||
|
||||
boolean brw_is_buffer_referenced_by_bo( struct brw_screen *brw_screen,
|
||||
struct pipe_buffer *buffer,
|
||||
struct brw_winsys_buffer *bo )
|
||||
{
|
||||
struct brw_buffer *buf = brw_buffer(buffer);
|
||||
if (buf->bo == NULL)
|
||||
return FALSE;
|
||||
|
||||
return brw_screen->sws->bo_references( bo, buf->bo );
|
||||
}
|
||||
|
||||
|
||||
void brw_screen_buffer_init(struct brw_screen *brw_screen)
|
||||
{
|
||||
brw_screen->base.buffer_create = brw_buffer_create;
|
||||
brw_screen->base.user_buffer_create = brw_user_buffer_create;
|
||||
brw_screen->base.buffer_map = brw_buffer_map;
|
||||
brw_screen->base.buffer_map_range = brw_buffer_map_range;
|
||||
brw_screen->base.buffer_flush_mapped_range = brw_buffer_flush_mapped_range;
|
||||
brw_screen->base.buffer_unmap = brw_buffer_unmap;
|
||||
brw_screen->base.buffer_destroy = brw_buffer_destroy;
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_simple_list.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "pipe/p_screen.h"
|
||||
#include "brw_screen.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_winsys.h"
|
||||
|
||||
enum {
|
||||
BRW_VIEW_LINEAR,
|
||||
BRW_VIEW_IN_PLACE
|
||||
};
|
||||
|
||||
|
||||
static boolean need_linear_view( struct brw_screen *brw_screen,
|
||||
struct brw_texture *brw_texture,
|
||||
union brw_surface_id id,
|
||||
unsigned usage )
|
||||
{
|
||||
#if 0
|
||||
/* XXX: what about IDGNG?
|
||||
*/
|
||||
if (!BRW_IS_G4X(brw->brw_screen->pci_id))
|
||||
{
|
||||
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
|
||||
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
|
||||
|
||||
/* The original gen4 hardware couldn't set up WM surfaces pointing
|
||||
* at an offset within a tile, which can happen when rendering to
|
||||
* anything but the base level of a texture or the +X face/0 depth.
|
||||
* This was fixed with the 4 Series hardware.
|
||||
*
|
||||
* For these original chips, you would have to make the depth and
|
||||
* color destination surfaces include information on the texture
|
||||
* type, LOD, face, and various limits to use them as a destination.
|
||||
*
|
||||
* This is easy in Gallium as surfaces are all backed by
|
||||
* textures, but there's also a nasty requirement that the depth
|
||||
* and the color surfaces all be of the same LOD, which is
|
||||
* harder to get around as we can't look at a surface in
|
||||
* isolation and decide if it's legal.
|
||||
*
|
||||
* Instead, end up being pessimistic and say that for i965,
|
||||
* ... ??
|
||||
*/
|
||||
if (brw_tex->tiling != I915_TILING_NONE &&
|
||||
(brw_tex_image_offset(brw_tex, face, level, zslize) & 4095)) {
|
||||
if (BRW_DEBUG & DEBUG_VIEW)
|
||||
debug_printf("%s: need surface view for non-aligned tex image\n",
|
||||
__FUNCTION__);
|
||||
return GL_TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Tiled 3d textures don't have subsets that look like 2d surfaces:
|
||||
*/
|
||||
|
||||
/* Everything else should be fine to render to in-place:
|
||||
*/
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* Look at all texture views and figure out if any of them need to be
|
||||
* back-copied into the texture for sampling
|
||||
*/
|
||||
void brw_update_texture( struct brw_screen *brw_screen,
|
||||
struct brw_texture *tex )
|
||||
{
|
||||
/* currently nothing to do */
|
||||
}
|
||||
|
||||
|
||||
/* Create a new surface with linear layout to serve as a render-target
|
||||
* where it would be illegal (perhaps due to tiling constraints) to do
|
||||
* this in-place.
|
||||
*
|
||||
* Currently not implmented, not sure if it's needed.
|
||||
*/
|
||||
static struct brw_surface *create_linear_view( struct brw_screen *brw_screen,
|
||||
struct brw_texture *tex,
|
||||
union brw_surface_id id,
|
||||
unsigned usage )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Create a pipe_surface that just points directly into the existing
|
||||
* texture's storage.
|
||||
*/
|
||||
static struct brw_surface *create_in_place_view( struct brw_screen *brw_screen,
|
||||
struct brw_texture *tex,
|
||||
union brw_surface_id id,
|
||||
unsigned usage )
|
||||
{
|
||||
struct brw_surface *surface;
|
||||
|
||||
surface = CALLOC_STRUCT(brw_surface);
|
||||
if (surface == NULL)
|
||||
return NULL;
|
||||
|
||||
pipe_reference_init(&surface->base.reference, 1);
|
||||
|
||||
/* XXX: ignoring render-to-slice-of-3d-texture
|
||||
*/
|
||||
assert(id.bits.zslice == 0);
|
||||
|
||||
surface->base.format = tex->base.format;
|
||||
surface->base.width = u_minify(tex->base.width0, id.bits.level);
|
||||
surface->base.height = u_minify(tex->base.height0, id.bits.level);
|
||||
surface->base.offset = tex->image_offset[id.bits.level][id.bits.face];
|
||||
surface->base.usage = usage;
|
||||
surface->base.zslice = id.bits.zslice;
|
||||
surface->base.face = id.bits.face;
|
||||
surface->base.level = id.bits.level;
|
||||
surface->id = id;
|
||||
surface->cpp = tex->cpp;
|
||||
surface->pitch = tex->pitch;
|
||||
surface->tiling = tex->tiling;
|
||||
|
||||
bo_reference( &surface->bo, tex->bo );
|
||||
pipe_texture_reference( &surface->base.texture, &tex->base );
|
||||
|
||||
surface->ss.ss0.surface_format = tex->ss.ss0.surface_format;
|
||||
surface->ss.ss0.surface_type = BRW_SURFACE_2D;
|
||||
|
||||
if (tex->tiling == BRW_TILING_NONE) {
|
||||
surface->ss.ss1.base_addr = surface->base.offset;
|
||||
} else {
|
||||
uint32_t tile_offset = surface->base.offset % 4096;
|
||||
|
||||
surface->ss.ss1.base_addr = surface->base.offset - tile_offset;
|
||||
|
||||
if (brw_screen->chipset.is_g4x) {
|
||||
if (tex->tiling == BRW_TILING_X) {
|
||||
/* Note that the low bits of these fields are missing, so
|
||||
* there's the possibility of getting in trouble.
|
||||
*/
|
||||
surface->ss.ss5.x_offset = (tile_offset % 512) / tex->cpp / 4;
|
||||
surface->ss.ss5.y_offset = tile_offset / 512 / 2;
|
||||
} else {
|
||||
surface->ss.ss5.x_offset = (tile_offset % 128) / tex->cpp / 4;
|
||||
surface->ss.ss5.y_offset = tile_offset / 128 / 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(tile_offset == 0);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (region_bo != NULL)
|
||||
surface->ss.ss1.base_addr += region_bo->offset; /* reloc */
|
||||
#endif
|
||||
|
||||
surface->ss.ss2.width = surface->base.width - 1;
|
||||
surface->ss.ss2.height = surface->base.height - 1;
|
||||
surface->ss.ss3.tiled_surface = tex->ss.ss3.tiled_surface;
|
||||
surface->ss.ss3.tile_walk = tex->ss.ss3.tile_walk;
|
||||
surface->ss.ss3.pitch = tex->ss.ss3.pitch;
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
/* Get a surface which is view into a texture
|
||||
*/
|
||||
static struct pipe_surface *brw_get_tex_surface(struct pipe_screen *screen,
|
||||
struct pipe_texture *pt,
|
||||
unsigned face, unsigned level,
|
||||
unsigned zslice,
|
||||
unsigned usage )
|
||||
{
|
||||
struct brw_texture *tex = brw_texture(pt);
|
||||
struct brw_screen *bscreen = brw_screen(screen);
|
||||
struct brw_surface *surface;
|
||||
union brw_surface_id id;
|
||||
int type;
|
||||
|
||||
id.bits.face = face;
|
||||
id.bits.level = level;
|
||||
id.bits.zslice = zslice;
|
||||
|
||||
if (need_linear_view(bscreen, tex, id, usage))
|
||||
type = BRW_VIEW_LINEAR;
|
||||
else
|
||||
type = BRW_VIEW_IN_PLACE;
|
||||
|
||||
|
||||
foreach (surface, &tex->views[type]) {
|
||||
if (id.value == surface->id.value)
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case BRW_VIEW_LINEAR:
|
||||
surface = create_linear_view( bscreen, tex, id, usage );
|
||||
break;
|
||||
case BRW_VIEW_IN_PLACE:
|
||||
surface = create_in_place_view( bscreen, tex, id, usage );
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
insert_at_head( &tex->views[type], surface );
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
|
||||
static void brw_tex_surface_destroy( struct pipe_surface *surf )
|
||||
{
|
||||
struct brw_surface *surface = brw_surface(surf);
|
||||
|
||||
/* Unreference texture, shared buffer:
|
||||
*/
|
||||
remove_from_list(surface);
|
||||
bo_reference(&surface->bo, NULL);
|
||||
pipe_texture_reference( &surface->base.texture, NULL );
|
||||
|
||||
|
||||
FREE(surface);
|
||||
}
|
||||
|
||||
|
||||
void brw_screen_tex_surface_init( struct brw_screen *brw_screen )
|
||||
{
|
||||
brw_screen->base.get_tex_surface = brw_get_tex_surface;
|
||||
brw_screen->base.tex_surface_destroy = brw_tex_surface_destroy;
|
||||
}
|
||||
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "pipe/p_format.h"
|
||||
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "brw_screen.h"
|
||||
#include "brw_debug.h"
|
||||
#include "brw_winsys.h"
|
||||
|
||||
/* Code to layout images in a mipmap tree for i965.
|
||||
*/
|
||||
|
||||
static int
|
||||
brw_tex_pitch_align (struct brw_texture *tex,
|
||||
int pitch)
|
||||
{
|
||||
if (!tex->compressed) {
|
||||
int pitch_align;
|
||||
|
||||
switch (tex->tiling) {
|
||||
case BRW_TILING_X:
|
||||
pitch_align = 512;
|
||||
break;
|
||||
case BRW_TILING_Y:
|
||||
pitch_align = 128;
|
||||
break;
|
||||
default:
|
||||
/* XXX: Untiled pitch alignment of 64 bytes for now to allow
|
||||
* render-to-texture to work in all cases. This should
|
||||
* probably be replaced at some point by some scheme to only
|
||||
* do this when really necessary, for example standalone
|
||||
* render target views.
|
||||
*/
|
||||
pitch_align = 64;
|
||||
break;
|
||||
}
|
||||
|
||||
pitch = align(pitch * tex->cpp, pitch_align);
|
||||
pitch /= tex->cpp;
|
||||
}
|
||||
|
||||
return pitch;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brw_tex_alignment_unit(enum pipe_format pf,
|
||||
GLuint *w, GLuint *h)
|
||||
{
|
||||
switch (pf) {
|
||||
case PIPE_FORMAT_DXT1_RGB:
|
||||
case PIPE_FORMAT_DXT1_RGBA:
|
||||
case PIPE_FORMAT_DXT3_RGBA:
|
||||
case PIPE_FORMAT_DXT5_RGBA:
|
||||
case PIPE_FORMAT_DXT1_SRGB:
|
||||
case PIPE_FORMAT_DXT1_SRGBA:
|
||||
case PIPE_FORMAT_DXT3_SRGBA:
|
||||
case PIPE_FORMAT_DXT5_SRGBA:
|
||||
*w = 4;
|
||||
*h = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
*w = 4;
|
||||
*h = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brw_tex_set_level_info(struct brw_texture *tex,
|
||||
GLuint level,
|
||||
GLuint nr_images,
|
||||
GLuint x, GLuint y,
|
||||
GLuint w, GLuint h, GLuint d)
|
||||
{
|
||||
|
||||
if (BRW_DEBUG & DEBUG_TEXTURE)
|
||||
debug_printf("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
|
||||
level, w, h, d, x, y, tex->level_offset[level]);
|
||||
|
||||
assert(tex->image_offset[level] == NULL);
|
||||
assert(nr_images >= 1);
|
||||
|
||||
tex->level_offset[level] = (x + y * tex->pitch) * tex->cpp;
|
||||
tex->nr_images[level] = nr_images;
|
||||
|
||||
tex->image_offset[level] = MALLOC(nr_images * sizeof(GLuint));
|
||||
tex->image_offset[level][0] = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brw_tex_set_image_offset(struct brw_texture *tex,
|
||||
GLuint level, GLuint img,
|
||||
GLuint x, GLuint y,
|
||||
GLuint offset)
|
||||
{
|
||||
assert((x == 0 && y == 0) || img != 0 || level != 0);
|
||||
assert(img < tex->nr_images[level]);
|
||||
|
||||
if (BRW_DEBUG & DEBUG_TEXTURE)
|
||||
debug_printf("%s level %d img %d pos %d,%d image_offset %x\n",
|
||||
__FUNCTION__, level, img, x, y,
|
||||
tex->image_offset[level][img]);
|
||||
|
||||
tex->image_offset[level][img] = (x + y * tex->pitch) * tex->cpp + offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void brw_layout_2d( struct brw_texture *tex )
|
||||
{
|
||||
GLuint align_h = 2, align_w = 4;
|
||||
GLuint level;
|
||||
GLuint x = 0;
|
||||
GLuint y = 0;
|
||||
GLuint width = tex->base.width0;
|
||||
GLuint height = tex->base.height0;
|
||||
|
||||
tex->pitch = tex->base.width0;
|
||||
brw_tex_alignment_unit(tex->base.format, &align_w, &align_h);
|
||||
|
||||
if (tex->compressed) {
|
||||
tex->pitch = align(tex->base.width0, align_w);
|
||||
}
|
||||
|
||||
/* May need to adjust pitch to accomodate the placement of
|
||||
* the 2nd mipmap. This occurs when the alignment
|
||||
* constraints of mipmap placement push the right edge of the
|
||||
* 2nd mipmap out past the width of its parent.
|
||||
*/
|
||||
if (tex->base.last_level > 0) {
|
||||
GLuint mip1_width;
|
||||
|
||||
if (tex->compressed) {
|
||||
mip1_width = (align(u_minify(tex->base.width0, 1), align_w) +
|
||||
align(u_minify(tex->base.width0, 2), align_w));
|
||||
} else {
|
||||
mip1_width = (align(u_minify(tex->base.width0, 1), align_w) +
|
||||
u_minify(tex->base.width0, 2));
|
||||
}
|
||||
|
||||
if (mip1_width > tex->pitch) {
|
||||
tex->pitch = mip1_width;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pitch must be a whole number of dwords, even though we
|
||||
* express it in texels.
|
||||
*/
|
||||
tex->pitch = brw_tex_pitch_align (tex, tex->pitch);
|
||||
tex->total_height = 0;
|
||||
|
||||
for ( level = 0 ; level <= tex->base.last_level ; level++ ) {
|
||||
GLuint img_height;
|
||||
|
||||
brw_tex_set_level_info(tex, level, 1, x, y, width, height, 1);
|
||||
|
||||
if (tex->compressed)
|
||||
img_height = MAX2(1, height/4);
|
||||
else
|
||||
img_height = align(height, align_h);
|
||||
|
||||
|
||||
/* Because the images are packed better, the final offset
|
||||
* might not be the maximal one:
|
||||
*/
|
||||
tex->total_height = MAX2(tex->total_height, y + img_height);
|
||||
|
||||
/* Layout_below: step right after second mipmap.
|
||||
*/
|
||||
if (level == 1) {
|
||||
x += align(width, align_w);
|
||||
}
|
||||
else {
|
||||
y += img_height;
|
||||
}
|
||||
|
||||
width = u_minify(width, 1);
|
||||
height = u_minify(height, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static boolean
|
||||
brw_layout_cubemap_idgng( struct brw_texture *tex )
|
||||
{
|
||||
GLuint align_h = 2, align_w = 4;
|
||||
GLuint level;
|
||||
GLuint x = 0;
|
||||
GLuint y = 0;
|
||||
GLuint width = tex->base.width0;
|
||||
GLuint height = tex->base.height0;
|
||||
GLuint qpitch = 0;
|
||||
GLuint y_pitch = 0;
|
||||
|
||||
tex->pitch = tex->base.width0;
|
||||
brw_tex_alignment_unit(tex->base.format, &align_w, &align_h);
|
||||
y_pitch = align(height, align_h);
|
||||
|
||||
if (tex->compressed) {
|
||||
tex->pitch = align(tex->base.width0, align_w);
|
||||
}
|
||||
|
||||
if (tex->base.last_level != 0) {
|
||||
GLuint mip1_width;
|
||||
|
||||
if (tex->compressed) {
|
||||
mip1_width = (align(u_minify(tex->base.width0, 1), align_w) +
|
||||
align(u_minify(tex->base.width0, 2), align_w));
|
||||
} else {
|
||||
mip1_width = (align(u_minify(tex->base.width0, 1), align_w) +
|
||||
u_minify(tex->base.width0, 2));
|
||||
}
|
||||
|
||||
if (mip1_width > tex->pitch) {
|
||||
tex->pitch = mip1_width;
|
||||
}
|
||||
}
|
||||
|
||||
tex->pitch = brw_tex_pitch_align(tex, tex->pitch);
|
||||
|
||||
if (tex->compressed) {
|
||||
qpitch = ((y_pitch +
|
||||
align(u_minify(y_pitch, 1), align_h) +
|
||||
11 * align_h) / 4) * tex->pitch * tex->cpp;
|
||||
|
||||
tex->total_height = ((y_pitch +
|
||||
align(u_minify(y_pitch, 1), align_h) +
|
||||
11 * align_h) / 4) * 6;
|
||||
} else {
|
||||
qpitch = (y_pitch +
|
||||
align(u_minify(y_pitch, 1), align_h) +
|
||||
11 * align_h) * tex->pitch * tex->cpp;
|
||||
|
||||
tex->total_height = (y_pitch +
|
||||
align(u_minify(y_pitch, 1), align_h) +
|
||||
11 * align_h) * 6;
|
||||
}
|
||||
|
||||
for (level = 0; level <= tex->base.last_level; level++) {
|
||||
GLuint img_height;
|
||||
GLuint nr_images = 6;
|
||||
GLuint q = 0;
|
||||
|
||||
brw_tex_set_level_info(tex, level, nr_images, x, y, width, height, 1);
|
||||
|
||||
for (q = 0; q < nr_images; q++)
|
||||
brw_tex_set_image_offset(tex, level, q, x, y, q * qpitch);
|
||||
|
||||
if (tex->compressed)
|
||||
img_height = MAX2(1, height/4);
|
||||
else
|
||||
img_height = align(height, align_h);
|
||||
|
||||
if (level == 1) {
|
||||
x += align(width, align_w);
|
||||
}
|
||||
else {
|
||||
y += img_height;
|
||||
}
|
||||
|
||||
width = u_minify(width, 1);
|
||||
height = u_minify(height, 1);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static boolean
|
||||
brw_layout_3d_cube( struct brw_texture *tex )
|
||||
{
|
||||
GLuint width = tex->base.width0;
|
||||
GLuint height = tex->base.height0;
|
||||
GLuint depth = tex->base.depth0;
|
||||
GLuint pack_x_pitch, pack_x_nr;
|
||||
GLuint pack_y_pitch;
|
||||
GLuint level;
|
||||
GLuint align_h = 2;
|
||||
GLuint align_w = 4;
|
||||
|
||||
tex->total_height = 0;
|
||||
brw_tex_alignment_unit(tex->base.format, &align_w, &align_h);
|
||||
|
||||
if (tex->compressed) {
|
||||
tex->pitch = align(width, align_w);
|
||||
pack_y_pitch = (height + 3) / 4;
|
||||
} else {
|
||||
tex->pitch = brw_tex_pitch_align(tex, tex->base.width0);
|
||||
pack_y_pitch = align(tex->base.height0, align_h);
|
||||
}
|
||||
|
||||
pack_x_pitch = width;
|
||||
pack_x_nr = 1;
|
||||
|
||||
for (level = 0 ; level <= tex->base.last_level ; level++) {
|
||||
GLuint nr_images = tex->base.target == PIPE_TEXTURE_3D ? depth : 6;
|
||||
GLint x = 0;
|
||||
GLint y = 0;
|
||||
GLint q, j;
|
||||
|
||||
brw_tex_set_level_info(tex, level, nr_images,
|
||||
0, tex->total_height,
|
||||
width, height, depth);
|
||||
|
||||
for (q = 0; q < nr_images;) {
|
||||
for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
|
||||
brw_tex_set_image_offset(tex, level, q, x, y, 0);
|
||||
x += pack_x_pitch;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
y += pack_y_pitch;
|
||||
}
|
||||
|
||||
|
||||
tex->total_height += y;
|
||||
width = u_minify(width, 1);
|
||||
height = u_minify(height, 1);
|
||||
depth = u_minify(depth, 1);
|
||||
|
||||
if (tex->compressed) {
|
||||
pack_y_pitch = (height + 3) / 4;
|
||||
|
||||
if (pack_x_pitch > align(width, align_w)) {
|
||||
pack_x_pitch = align(width, align_w);
|
||||
pack_x_nr <<= 1;
|
||||
}
|
||||
} else {
|
||||
if (pack_x_pitch > 4) {
|
||||
pack_x_pitch >>= 1;
|
||||
pack_x_nr <<= 1;
|
||||
assert(pack_x_pitch * pack_x_nr <= tex->pitch);
|
||||
}
|
||||
|
||||
if (pack_y_pitch > 2) {
|
||||
pack_y_pitch >>= 1;
|
||||
pack_y_pitch = align(pack_y_pitch, align_h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The 965's sampler lays cachelines out according to how accesses
|
||||
* in the texture surfaces run, so they may be "vertical" through
|
||||
* memory. As a result, the docs say in Surface Padding Requirements:
|
||||
* Sampling Engine Surfaces that two extra rows of padding are required.
|
||||
*/
|
||||
if (tex->base.target == PIPE_TEXTURE_CUBE)
|
||||
tex->total_height += 2;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLboolean brw_texture_layout(struct brw_screen *brw_screen,
|
||||
struct brw_texture *tex )
|
||||
{
|
||||
switch (tex->base.target) {
|
||||
case PIPE_TEXTURE_CUBE:
|
||||
if (brw_screen->chipset.is_igdng)
|
||||
brw_layout_cubemap_idgng( tex );
|
||||
else
|
||||
brw_layout_3d_cube( tex );
|
||||
break;
|
||||
|
||||
case PIPE_TEXTURE_3D:
|
||||
brw_layout_3d_cube( tex );
|
||||
break;
|
||||
|
||||
default:
|
||||
brw_layout_2d( tex );
|
||||
break;
|
||||
}
|
||||
|
||||
if (BRW_DEBUG & DEBUG_TEXTURE)
|
||||
debug_printf("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
|
||||
tex->pitch,
|
||||
tex->total_height,
|
||||
tex->cpp,
|
||||
tex->pitch * tex->total_height * tex->cpp );
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_simple_list.h"
|
||||
|
||||
#include "brw_screen.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_structs.h"
|
||||
#include "brw_winsys.h"
|
||||
|
||||
|
||||
|
||||
static GLuint translate_tex_target( unsigned target )
|
||||
{
|
||||
switch (target) {
|
||||
case PIPE_TEXTURE_1D:
|
||||
return BRW_SURFACE_1D;
|
||||
|
||||
case PIPE_TEXTURE_2D:
|
||||
return BRW_SURFACE_2D;
|
||||
|
||||
case PIPE_TEXTURE_3D:
|
||||
return BRW_SURFACE_3D;
|
||||
|
||||
case PIPE_TEXTURE_CUBE:
|
||||
return BRW_SURFACE_CUBE;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return BRW_SURFACE_1D;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static GLuint translate_tex_format( enum pipe_format pf )
|
||||
{
|
||||
switch( pf ) {
|
||||
case PIPE_FORMAT_L8_UNORM:
|
||||
return BRW_SURFACEFORMAT_L8_UNORM;
|
||||
|
||||
case PIPE_FORMAT_I8_UNORM:
|
||||
return BRW_SURFACEFORMAT_I8_UNORM;
|
||||
|
||||
case PIPE_FORMAT_A8_UNORM:
|
||||
return BRW_SURFACEFORMAT_A8_UNORM;
|
||||
|
||||
case PIPE_FORMAT_L16_UNORM:
|
||||
return BRW_SURFACEFORMAT_L16_UNORM;
|
||||
|
||||
/* XXX: Add these to gallium
|
||||
case PIPE_FORMAT_I16_UNORM:
|
||||
return BRW_SURFACEFORMAT_I16_UNORM;
|
||||
|
||||
case PIPE_FORMAT_A16_UNORM:
|
||||
return BRW_SURFACEFORMAT_A16_UNORM;
|
||||
*/
|
||||
|
||||
case PIPE_FORMAT_A8L8_UNORM:
|
||||
return BRW_SURFACEFORMAT_L8A8_UNORM;
|
||||
|
||||
case PIPE_FORMAT_R5G6B5_UNORM:
|
||||
return BRW_SURFACEFORMAT_B5G6R5_UNORM;
|
||||
|
||||
case PIPE_FORMAT_A1R5G5B5_UNORM:
|
||||
return BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
|
||||
|
||||
case PIPE_FORMAT_A4R4G4B4_UNORM:
|
||||
return BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
|
||||
|
||||
case PIPE_FORMAT_X8R8G8B8_UNORM:
|
||||
return BRW_SURFACEFORMAT_R8G8B8X8_UNORM;
|
||||
|
||||
case PIPE_FORMAT_A8R8G8B8_UNORM:
|
||||
return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
/*
|
||||
* Video formats
|
||||
*/
|
||||
|
||||
case PIPE_FORMAT_YCBCR_REV:
|
||||
return BRW_SURFACEFORMAT_YCRCB_NORMAL;
|
||||
|
||||
case PIPE_FORMAT_YCBCR:
|
||||
return BRW_SURFACEFORMAT_YCRCB_SWAPUVY;
|
||||
|
||||
/*
|
||||
* Compressed formats.
|
||||
*/
|
||||
/* XXX: Add FXT to gallium?
|
||||
case PIPE_FORMAT_FXT1_RGBA:
|
||||
return BRW_SURFACEFORMAT_FXT1;
|
||||
*/
|
||||
|
||||
case PIPE_FORMAT_DXT1_RGB:
|
||||
return BRW_SURFACEFORMAT_DXT1_RGB;
|
||||
|
||||
case PIPE_FORMAT_DXT1_RGBA:
|
||||
return BRW_SURFACEFORMAT_BC1_UNORM;
|
||||
|
||||
case PIPE_FORMAT_DXT3_RGBA:
|
||||
return BRW_SURFACEFORMAT_BC2_UNORM;
|
||||
|
||||
case PIPE_FORMAT_DXT5_RGBA:
|
||||
return BRW_SURFACEFORMAT_BC3_UNORM;
|
||||
|
||||
/*
|
||||
* sRGB formats
|
||||
*/
|
||||
|
||||
case PIPE_FORMAT_R8G8B8A8_SRGB:
|
||||
return BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB;
|
||||
|
||||
case PIPE_FORMAT_A8L8_SRGB:
|
||||
return BRW_SURFACEFORMAT_L8A8_UNORM_SRGB;
|
||||
|
||||
case PIPE_FORMAT_L8_SRGB:
|
||||
return BRW_SURFACEFORMAT_L8_UNORM_SRGB;
|
||||
|
||||
case PIPE_FORMAT_DXT1_SRGB:
|
||||
return BRW_SURFACEFORMAT_BC1_UNORM_SRGB;
|
||||
|
||||
/*
|
||||
* Depth formats
|
||||
*/
|
||||
|
||||
case PIPE_FORMAT_Z16_UNORM:
|
||||
return BRW_SURFACEFORMAT_I16_UNORM;
|
||||
|
||||
case PIPE_FORMAT_S8Z24_UNORM:
|
||||
case PIPE_FORMAT_X8Z24_UNORM:
|
||||
return BRW_SURFACEFORMAT_I24X8_UNORM;
|
||||
|
||||
case PIPE_FORMAT_Z32_FLOAT:
|
||||
return BRW_SURFACEFORMAT_I32_FLOAT;
|
||||
|
||||
/* XXX: presumably for bump mapping. Add this to mesa state
|
||||
* tracker?
|
||||
*
|
||||
* XXX: Add flipped versions of these formats to Gallium.
|
||||
*/
|
||||
case PIPE_FORMAT_R8G8_SNORM:
|
||||
return BRW_SURFACEFORMAT_R8G8_SNORM;
|
||||
|
||||
case PIPE_FORMAT_R8G8B8A8_SNORM:
|
||||
return BRW_SURFACEFORMAT_R8G8B8A8_SNORM;
|
||||
|
||||
default:
|
||||
return BRW_SURFACEFORMAT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static struct pipe_texture *brw_texture_create( struct pipe_screen *screen,
|
||||
const struct pipe_texture *templ )
|
||||
|
||||
{
|
||||
struct brw_screen *bscreen = brw_screen(screen);
|
||||
struct brw_texture *tex;
|
||||
enum brw_buffer_type buffer_type;
|
||||
enum pipe_error ret;
|
||||
|
||||
tex = CALLOC_STRUCT(brw_texture);
|
||||
if (tex == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy(&tex->base, templ, sizeof *templ);
|
||||
pipe_reference_init(&tex->base.reference, 1);
|
||||
tex->base.screen = screen;
|
||||
|
||||
/* XXX: compressed textures need special treatment here
|
||||
*/
|
||||
tex->cpp = pf_get_size(tex->base.format);
|
||||
tex->compressed = pf_is_compressed(tex->base.format);
|
||||
|
||||
make_empty_list(&tex->views[0]);
|
||||
make_empty_list(&tex->views[1]);
|
||||
|
||||
/* XXX: No tiling with compressed textures??
|
||||
*/
|
||||
if (tex->compressed == 0 &&
|
||||
!bscreen->no_tiling)
|
||||
{
|
||||
if (bscreen->chipset.is_965 &&
|
||||
pf_is_depth_or_stencil(templ->format))
|
||||
tex->tiling = BRW_TILING_Y;
|
||||
else
|
||||
tex->tiling = BRW_TILING_X;
|
||||
}
|
||||
else {
|
||||
tex->tiling = BRW_TILING_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (!brw_texture_layout( bscreen, tex ))
|
||||
goto fail;
|
||||
|
||||
|
||||
if (templ->tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
|
||||
PIPE_TEXTURE_USAGE_PRIMARY)) {
|
||||
buffer_type = BRW_BUFFER_TYPE_SCANOUT;
|
||||
}
|
||||
else {
|
||||
buffer_type = BRW_BUFFER_TYPE_TEXTURE;
|
||||
}
|
||||
|
||||
ret = bscreen->sws->bo_alloc( bscreen->sws,
|
||||
buffer_type,
|
||||
tex->pitch * tex->total_height * tex->cpp,
|
||||
64,
|
||||
&tex->bo );
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
|
||||
tex->ss.ss0.surface_type = translate_tex_target(tex->base.target);
|
||||
tex->ss.ss0.surface_format = translate_tex_format(tex->base.format);
|
||||
assert(tex->ss.ss0.surface_format != BRW_SURFACEFORMAT_INVALID);
|
||||
|
||||
/* This is ok for all textures with channel width 8bit or less:
|
||||
*/
|
||||
/* tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
|
||||
|
||||
|
||||
/* XXX: what happens when tex->bo->offset changes???
|
||||
*/
|
||||
tex->ss.ss1.base_addr = 0; /* reloc */
|
||||
tex->ss.ss2.mip_count = tex->base.last_level;
|
||||
tex->ss.ss2.width = tex->base.width0 - 1;
|
||||
tex->ss.ss2.height = tex->base.height0 - 1;
|
||||
|
||||
switch (tex->tiling) {
|
||||
case BRW_TILING_NONE:
|
||||
tex->ss.ss3.tiled_surface = 0;
|
||||
tex->ss.ss3.tile_walk = 0;
|
||||
break;
|
||||
case BRW_TILING_X:
|
||||
tex->ss.ss3.tiled_surface = 1;
|
||||
tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR;
|
||||
break;
|
||||
case BRW_TILING_Y:
|
||||
tex->ss.ss3.tiled_surface = 1;
|
||||
tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR;
|
||||
break;
|
||||
}
|
||||
|
||||
tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1;
|
||||
tex->ss.ss3.depth = tex->base.depth0 - 1;
|
||||
|
||||
tex->ss.ss4.min_lod = 0;
|
||||
|
||||
if (tex->base.target == PIPE_TEXTURE_CUBE) {
|
||||
tex->ss.ss0.cube_pos_x = 1;
|
||||
tex->ss.ss0.cube_pos_y = 1;
|
||||
tex->ss.ss0.cube_pos_z = 1;
|
||||
tex->ss.ss0.cube_neg_x = 1;
|
||||
tex->ss.ss0.cube_neg_y = 1;
|
||||
tex->ss.ss0.cube_neg_z = 1;
|
||||
}
|
||||
|
||||
return &tex->base;
|
||||
|
||||
fail:
|
||||
bo_reference(&tex->bo, NULL);
|
||||
FREE(tex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct pipe_texture *brw_texture_blanket(struct pipe_screen *screen,
|
||||
const struct pipe_texture *templ,
|
||||
const unsigned *stride,
|
||||
struct pipe_buffer *buffer)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void brw_texture_destroy(struct pipe_texture *pt)
|
||||
{
|
||||
struct brw_texture *tex = brw_texture(pt);
|
||||
bo_reference(&tex->bo, NULL);
|
||||
FREE(pt);
|
||||
}
|
||||
|
||||
|
||||
static boolean brw_is_format_supported( struct pipe_screen *screen,
|
||||
enum pipe_format format,
|
||||
enum pipe_texture_target target,
|
||||
unsigned tex_usage,
|
||||
unsigned geom_flags )
|
||||
{
|
||||
return translate_tex_format(format) != BRW_SURFACEFORMAT_INVALID;
|
||||
}
|
||||
|
||||
|
||||
boolean brw_is_texture_referenced_by_bo( struct brw_screen *brw_screen,
|
||||
struct pipe_texture *texture,
|
||||
unsigned face,
|
||||
unsigned level,
|
||||
struct brw_winsys_buffer *bo )
|
||||
{
|
||||
struct brw_texture *tex = brw_texture(texture);
|
||||
struct brw_surface *surf;
|
||||
int i;
|
||||
|
||||
/* XXX: this is subject to false positives if the underlying
|
||||
* texture BO is referenced, we can't tell whether the sub-region
|
||||
* we care about participates in that.
|
||||
*/
|
||||
if (brw_screen->sws->bo_references( bo, tex->bo ))
|
||||
return TRUE;
|
||||
|
||||
/* Find any view on this texture for this face/level and see if it
|
||||
* is referenced:
|
||||
*/
|
||||
for (i = 0; i < 2; i++) {
|
||||
foreach (surf, &tex->views[i]) {
|
||||
if (surf->bo == tex->bo)
|
||||
continue;
|
||||
|
||||
if (surf->id.bits.face != face ||
|
||||
surf->id.bits.level != level)
|
||||
continue;
|
||||
|
||||
if (brw_screen->sws->bo_references( bo, surf->bo))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Transfer functions
|
||||
*/
|
||||
|
||||
static struct pipe_transfer*
|
||||
brw_get_tex_transfer(struct pipe_screen *screen,
|
||||
struct pipe_texture *texture,
|
||||
unsigned face, unsigned level, unsigned zslice,
|
||||
enum pipe_transfer_usage usage, unsigned x, unsigned y,
|
||||
unsigned w, unsigned h)
|
||||
{
|
||||
struct brw_texture *tex = brw_texture(texture);
|
||||
struct brw_transfer *trans;
|
||||
unsigned offset; /* in bytes */
|
||||
|
||||
if (texture->target == PIPE_TEXTURE_CUBE) {
|
||||
offset = tex->image_offset[level][face];
|
||||
} else if (texture->target == PIPE_TEXTURE_3D) {
|
||||
offset = tex->image_offset[level][zslice];
|
||||
} else {
|
||||
offset = tex->image_offset[level][0];
|
||||
assert(face == 0);
|
||||
assert(zslice == 0);
|
||||
}
|
||||
|
||||
trans = CALLOC_STRUCT(brw_transfer);
|
||||
if (trans) {
|
||||
pipe_texture_reference(&trans->base.texture, texture);
|
||||
trans->base.format = trans->base.format;
|
||||
trans->base.x = x;
|
||||
trans->base.y = y;
|
||||
trans->base.width = w;
|
||||
trans->base.height = h;
|
||||
trans->base.block = texture->block;
|
||||
trans->base.nblocksx = texture->nblocksx[level];
|
||||
trans->base.nblocksy = texture->nblocksy[level];
|
||||
trans->base.stride = tex->pitch * tex->cpp;
|
||||
trans->offset = offset;
|
||||
trans->base.usage = usage;
|
||||
}
|
||||
return &trans->base;
|
||||
}
|
||||
|
||||
static void *
|
||||
brw_transfer_map(struct pipe_screen *screen,
|
||||
struct pipe_transfer *transfer)
|
||||
{
|
||||
struct brw_texture *tex = brw_texture(transfer->texture);
|
||||
struct brw_winsys_screen *sws = brw_screen(screen)->sws;
|
||||
char *map;
|
||||
unsigned usage = transfer->usage;
|
||||
|
||||
map = sws->bo_map(tex->bo,
|
||||
BRW_DATA_OTHER,
|
||||
0,
|
||||
tex->bo->size,
|
||||
(usage & PIPE_TRANSFER_WRITE) ? TRUE : FALSE,
|
||||
(usage & 0) ? TRUE : FALSE,
|
||||
(usage & 0) ? TRUE : FALSE);
|
||||
|
||||
if (!map)
|
||||
return NULL;
|
||||
|
||||
return map + brw_transfer(transfer)->offset +
|
||||
transfer->y / transfer->block.height * transfer->stride +
|
||||
transfer->x / transfer->block.width * transfer->block.size;
|
||||
}
|
||||
|
||||
static void
|
||||
brw_transfer_unmap(struct pipe_screen *screen,
|
||||
struct pipe_transfer *transfer)
|
||||
{
|
||||
struct brw_texture *tex = brw_texture(transfer->texture);
|
||||
struct brw_winsys_screen *sws = brw_screen(screen)->sws;
|
||||
|
||||
sws->bo_unmap(tex->bo);
|
||||
}
|
||||
|
||||
static void
|
||||
brw_tex_transfer_destroy(struct pipe_transfer *trans)
|
||||
{
|
||||
pipe_texture_reference(&trans->texture, NULL);
|
||||
FREE(trans);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Functions exported to the winsys
|
||||
*/
|
||||
|
||||
boolean brw_texture_get_winsys_buffer(struct pipe_texture *texture,
|
||||
struct brw_winsys_buffer **buffer,
|
||||
unsigned *stride)
|
||||
{
|
||||
struct brw_texture *tex = brw_texture(texture);
|
||||
|
||||
*buffer = tex->bo;
|
||||
if (stride)
|
||||
*stride = tex->pitch * tex->cpp;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct pipe_texture *
|
||||
brw_texture_blanket_winsys_buffer(struct pipe_screen *screen,
|
||||
const struct pipe_texture *templ,
|
||||
unsigned pitch,
|
||||
unsigned tiling,
|
||||
struct brw_winsys_buffer *buffer)
|
||||
{
|
||||
struct brw_screen *bscreen = brw_screen(screen);
|
||||
struct brw_texture *tex;
|
||||
|
||||
if (templ->target != PIPE_TEXTURE_2D ||
|
||||
templ->last_level != 0 ||
|
||||
templ->depth0 != 1)
|
||||
return NULL;
|
||||
|
||||
if (pf_is_compressed(templ->format))
|
||||
return NULL;
|
||||
|
||||
tex = CALLOC_STRUCT(brw_texture);
|
||||
if (!tex)
|
||||
return NULL;
|
||||
|
||||
memcpy(&tex->base, templ, sizeof *templ);
|
||||
pipe_reference_init(&tex->base.reference, 1);
|
||||
tex->base.screen = screen;
|
||||
|
||||
tex->cpp = pf_get_size(tex->base.format);
|
||||
tex->tiling = tiling;
|
||||
|
||||
make_empty_list(&tex->views[0]);
|
||||
make_empty_list(&tex->views[1]);
|
||||
|
||||
if (!brw_texture_layout(bscreen, tex))
|
||||
goto fail;
|
||||
|
||||
/* XXX Maybe some more checks? */
|
||||
if ((pitch / tex->cpp) < tex->pitch)
|
||||
goto fail;
|
||||
|
||||
tex->pitch = pitch / tex->cpp;
|
||||
|
||||
tex->bo = buffer;
|
||||
|
||||
/* fix this warning */
|
||||
#if 0
|
||||
if (tex->size > buffer->size)
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
|
||||
tex->ss.ss0.surface_type = translate_tex_target(tex->base.target);
|
||||
tex->ss.ss0.surface_format = translate_tex_format(tex->base.format);
|
||||
assert(tex->ss.ss0.surface_format != BRW_SURFACEFORMAT_INVALID);
|
||||
|
||||
/* This is ok for all textures with channel width 8bit or less:
|
||||
*/
|
||||
/* tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
|
||||
|
||||
|
||||
/* XXX: what happens when tex->bo->offset changes???
|
||||
*/
|
||||
tex->ss.ss1.base_addr = 0; /* reloc */
|
||||
tex->ss.ss2.mip_count = tex->base.last_level;
|
||||
tex->ss.ss2.width = tex->base.width0 - 1;
|
||||
tex->ss.ss2.height = tex->base.height0 - 1;
|
||||
|
||||
switch (tex->tiling) {
|
||||
case BRW_TILING_NONE:
|
||||
tex->ss.ss3.tiled_surface = 0;
|
||||
tex->ss.ss3.tile_walk = 0;
|
||||
break;
|
||||
case BRW_TILING_X:
|
||||
tex->ss.ss3.tiled_surface = 1;
|
||||
tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR;
|
||||
break;
|
||||
case BRW_TILING_Y:
|
||||
tex->ss.ss3.tiled_surface = 1;
|
||||
tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR;
|
||||
break;
|
||||
}
|
||||
|
||||
tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1;
|
||||
tex->ss.ss3.depth = tex->base.depth0 - 1;
|
||||
|
||||
tex->ss.ss4.min_lod = 0;
|
||||
|
||||
return &tex->base;
|
||||
|
||||
fail:
|
||||
FREE(tex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void brw_screen_tex_init( struct brw_screen *brw_screen )
|
||||
{
|
||||
brw_screen->base.is_format_supported = brw_is_format_supported;
|
||||
brw_screen->base.texture_create = brw_texture_create;
|
||||
brw_screen->base.texture_destroy = brw_texture_destroy;
|
||||
brw_screen->base.texture_blanket = brw_texture_blanket;
|
||||
brw_screen->base.get_tex_transfer = brw_get_tex_transfer;
|
||||
brw_screen->base.transfer_map = brw_transfer_map;
|
||||
brw_screen->base.transfer_unmap = brw_transfer_unmap;
|
||||
brw_screen->base.tex_transfer_destroy = brw_tex_transfer_destroy;
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_pipe_rast.h"
|
||||
#include "brw_eu.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_sf.h"
|
||||
#include "brw_state.h"
|
||||
|
||||
static enum pipe_error compile_sf_prog( struct brw_context *brw,
|
||||
struct brw_sf_prog_key *key,
|
||||
struct brw_winsys_buffer **bo_out )
|
||||
{
|
||||
enum pipe_error ret;
|
||||
struct brw_sf_compile c;
|
||||
const GLuint *program;
|
||||
GLuint program_size;
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
/* Begin the compilation:
|
||||
*/
|
||||
brw_init_compile(brw, &c.func);
|
||||
|
||||
c.key = *key;
|
||||
c.nr_attrs = c.key.nr_attrs;
|
||||
c.nr_attr_regs = (c.nr_attrs+1)/2;
|
||||
c.nr_setup_attrs = c.key.nr_attrs;
|
||||
c.nr_setup_regs = (c.nr_setup_attrs+1)/2;
|
||||
|
||||
c.prog_data.urb_read_length = c.nr_attr_regs;
|
||||
c.prog_data.urb_entry_size = c.nr_setup_regs * 2;
|
||||
|
||||
/* Special case when there are no attributes to setup.
|
||||
*
|
||||
* XXX: should be able to set nr_setup_attrs to nr_attrs-1 -- but
|
||||
* breaks vp-tris.c
|
||||
*/
|
||||
if (c.nr_attrs - 1 == 0) {
|
||||
c.nr_verts = 0;
|
||||
brw_emit_null_setup( &c );
|
||||
}
|
||||
else {
|
||||
/* Which primitive? Or all three?
|
||||
*/
|
||||
switch (key->primitive) {
|
||||
case SF_TRIANGLES:
|
||||
c.nr_verts = 3;
|
||||
brw_emit_tri_setup( &c, GL_TRUE );
|
||||
break;
|
||||
case SF_LINES:
|
||||
c.nr_verts = 2;
|
||||
brw_emit_line_setup( &c, GL_TRUE );
|
||||
break;
|
||||
case SF_POINTS:
|
||||
c.nr_verts = 1;
|
||||
if (key->do_point_sprite)
|
||||
brw_emit_point_sprite_setup( &c, GL_TRUE );
|
||||
else
|
||||
brw_emit_point_setup( &c, GL_TRUE );
|
||||
break;
|
||||
case SF_UNFILLED_TRIS:
|
||||
c.nr_verts = 3;
|
||||
brw_emit_anyprim_setup( &c );
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return PIPE_ERROR_BAD_INPUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the program
|
||||
*/
|
||||
ret = brw_get_program(&c.func, &program, &program_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Upload
|
||||
*/
|
||||
ret = brw_upload_cache( &brw->cache, BRW_SF_PROG,
|
||||
&c.key, sizeof(c.key),
|
||||
NULL, 0,
|
||||
program, program_size,
|
||||
&c.prog_data,
|
||||
&brw->sf.prog_data,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
/* Calculate interpolants for triangle and line rasterization.
|
||||
*/
|
||||
static enum pipe_error upload_sf_prog(struct brw_context *brw)
|
||||
{
|
||||
const struct brw_fs_signature *sig = &brw->curr.fragment_shader->signature;
|
||||
struct brw_sf_prog_key key;
|
||||
enum pipe_error ret;
|
||||
unsigned i;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
|
||||
/* Populate the key, noting state dependencies:
|
||||
*/
|
||||
|
||||
/* XXX: Add one to account for the position input.
|
||||
*/
|
||||
/* PIPE_NEW_FRAGMENT_SIGNATURE */
|
||||
key.nr_attrs = sig->nr_inputs + 1;
|
||||
|
||||
|
||||
/* XXX: why is position required to be linear? why do we care
|
||||
* about it at all?
|
||||
*/
|
||||
key.linear_attrs = 1; /* position -- but why? */
|
||||
|
||||
for (i = 0; i < sig->nr_inputs; i++) {
|
||||
switch (sig->input[i].interp) {
|
||||
case TGSI_INTERPOLATE_CONSTANT:
|
||||
break;
|
||||
case TGSI_INTERPOLATE_LINEAR:
|
||||
key.linear_attrs |= 1 << (i+1);
|
||||
break;
|
||||
case TGSI_INTERPOLATE_PERSPECTIVE:
|
||||
key.persp_attrs |= 1 << (i+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* BRW_NEW_REDUCED_PRIMITIVE */
|
||||
switch (brw->reduced_primitive) {
|
||||
case PIPE_PRIM_TRIANGLES:
|
||||
/* PIPE_NEW_RAST
|
||||
*/
|
||||
if (brw->curr.rast->templ.fill_cw != PIPE_POLYGON_MODE_FILL ||
|
||||
brw->curr.rast->templ.fill_ccw != PIPE_POLYGON_MODE_FILL)
|
||||
key.primitive = SF_UNFILLED_TRIS;
|
||||
else
|
||||
key.primitive = SF_TRIANGLES;
|
||||
break;
|
||||
case PIPE_PRIM_LINES:
|
||||
key.primitive = SF_LINES;
|
||||
break;
|
||||
case PIPE_PRIM_POINTS:
|
||||
key.primitive = SF_POINTS;
|
||||
break;
|
||||
}
|
||||
|
||||
key.do_point_sprite = brw->curr.rast->templ.point_sprite;
|
||||
key.sprite_origin_lower_left = 0; /* XXX: ctx->Point.SpriteOrigin - fix rast state */
|
||||
key.do_flat_shading = brw->curr.rast->templ.flatshade;
|
||||
key.do_twoside_color = brw->curr.rast->templ.light_twoside;
|
||||
|
||||
if (key.do_twoside_color) {
|
||||
key.frontface_ccw = (brw->curr.rast->templ.front_winding ==
|
||||
PIPE_WINDING_CCW);
|
||||
}
|
||||
|
||||
if (brw_search_cache(&brw->cache, BRW_SF_PROG,
|
||||
&key, sizeof(key),
|
||||
NULL, 0,
|
||||
&brw->sf.prog_data,
|
||||
&brw->sf.prog_bo))
|
||||
return PIPE_OK;
|
||||
|
||||
ret = compile_sf_prog( brw, &key, &brw->sf.prog_bo );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
const struct brw_tracked_state brw_sf_prog = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_RAST | PIPE_NEW_FRAGMENT_SIGNATURE),
|
||||
.brw = (BRW_NEW_REDUCED_PRIMITIVE),
|
||||
.cache = 0
|
||||
},
|
||||
.prepare = upload_sf_prog
|
||||
};
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BRW_SF_H
|
||||
#define BRW_SF_H
|
||||
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_eu.h"
|
||||
|
||||
|
||||
#define SF_POINTS 0
|
||||
#define SF_LINES 1
|
||||
#define SF_TRIANGLES 2
|
||||
#define SF_UNFILLED_TRIS 3
|
||||
|
||||
struct brw_sf_prog_key {
|
||||
|
||||
/* Bitmask of linear and perspective interpolated inputs, 0..nr
|
||||
*/
|
||||
GLuint persp_attrs:32;
|
||||
GLuint linear_attrs:32;
|
||||
GLuint point_coord_replace_attrs:32;
|
||||
|
||||
GLuint nr_attrs:8;
|
||||
GLuint primitive:2;
|
||||
GLuint do_twoside_color:1;
|
||||
GLuint do_flat_shading:1;
|
||||
GLuint frontface_ccw:1;
|
||||
GLuint do_point_sprite:1;
|
||||
GLuint sprite_origin_lower_left:1;
|
||||
GLuint pad:17;
|
||||
|
||||
GLuint attr_col0:8;
|
||||
GLuint attr_col1:8;
|
||||
GLuint attr_bfc0:8;
|
||||
GLuint attr_bfc1:8;
|
||||
};
|
||||
|
||||
struct brw_sf_point_tex {
|
||||
GLboolean CoordReplace;
|
||||
};
|
||||
|
||||
struct brw_sf_compile {
|
||||
struct brw_compile func;
|
||||
struct brw_sf_prog_key key;
|
||||
struct brw_sf_prog_data prog_data;
|
||||
|
||||
struct brw_reg pv;
|
||||
struct brw_reg det;
|
||||
struct brw_reg dx0;
|
||||
struct brw_reg dx2;
|
||||
struct brw_reg dy0;
|
||||
struct brw_reg dy2;
|
||||
|
||||
/* z and 1/w passed in seperately:
|
||||
*/
|
||||
struct brw_reg z[3];
|
||||
struct brw_reg inv_w[3];
|
||||
|
||||
/* The vertices:
|
||||
*/
|
||||
struct brw_reg vert[3];
|
||||
|
||||
/* Temporaries, allocated after last vertex reg.
|
||||
*/
|
||||
struct brw_reg inv_det;
|
||||
struct brw_reg a1_sub_a0;
|
||||
struct brw_reg a2_sub_a0;
|
||||
struct brw_reg tmp;
|
||||
|
||||
struct brw_reg m1Cx;
|
||||
struct brw_reg m2Cy;
|
||||
struct brw_reg m3C0;
|
||||
|
||||
GLuint nr_verts;
|
||||
GLuint nr_attrs;
|
||||
GLuint nr_attr_regs;
|
||||
GLuint nr_setup_attrs;
|
||||
GLuint nr_setup_regs;
|
||||
|
||||
GLuint point_coord_replace_mask;
|
||||
};
|
||||
|
||||
|
||||
void brw_emit_null_setup( struct brw_sf_compile *c );
|
||||
void brw_emit_tri_setup( struct brw_sf_compile *c, GLboolean allocate );
|
||||
void brw_emit_line_setup( struct brw_sf_compile *c, GLboolean allocate );
|
||||
void brw_emit_point_setup( struct brw_sf_compile *c, GLboolean allocate );
|
||||
void brw_emit_point_sprite_setup( struct brw_sf_compile *c, GLboolean allocate );
|
||||
void brw_emit_anyprim_setup( struct brw_sf_compile *c );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,765 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "brw_batchbuffer.h"
|
||||
|
||||
#include "brw_defines.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_eu.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_sf.h"
|
||||
|
||||
|
||||
static struct brw_reg get_vert_attr(struct brw_sf_compile *c,
|
||||
struct brw_reg vert,
|
||||
GLuint attr)
|
||||
{
|
||||
GLuint off = attr / 2;
|
||||
GLuint sub = attr % 2;
|
||||
|
||||
return brw_vec4_grf(vert.nr + off, sub * 4);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Twoside lighting
|
||||
*/
|
||||
static void copy_bfc( struct brw_sf_compile *c,
|
||||
struct brw_reg vert )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
|
||||
if (c->key.attr_col0 && c->key.attr_bfc0)
|
||||
brw_MOV(p,
|
||||
get_vert_attr(c, vert, c->key.attr_col0),
|
||||
get_vert_attr(c, vert, c->key.attr_bfc0));
|
||||
|
||||
if (c->key.attr_col1 && c->key.attr_bfc1)
|
||||
brw_MOV(p,
|
||||
get_vert_attr(c, vert, c->key.attr_col1),
|
||||
get_vert_attr(c, vert, c->key.attr_bfc1));
|
||||
}
|
||||
|
||||
|
||||
static void do_twoside_color( struct brw_sf_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_instruction *if_insn;
|
||||
GLuint backface_conditional = c->key.frontface_ccw ? BRW_CONDITIONAL_G : BRW_CONDITIONAL_L;
|
||||
|
||||
/* Already done in clip program:
|
||||
*/
|
||||
if (c->key.primitive == SF_UNFILLED_TRIS)
|
||||
return;
|
||||
|
||||
/* XXX: What happens if BFC isn't present? This could only happen
|
||||
* for user-supplied vertex programs, as t_vp_build.c always does
|
||||
* the right thing.
|
||||
*/
|
||||
if (!(c->key.attr_col0 && c->key.attr_bfc0) &&
|
||||
!(c->key.attr_col1 && c->key.attr_bfc1))
|
||||
return;
|
||||
|
||||
/* Need to use BRW_EXECUTE_4 and also do an 4-wide compare in order
|
||||
* to get all channels active inside the IF. In the clipping code
|
||||
* we run with NoMask, so it's not an option and we can use
|
||||
* BRW_EXECUTE_1 for all comparisions.
|
||||
*/
|
||||
brw_push_insn_state(p);
|
||||
brw_CMP(p, vec4(brw_null_reg()), backface_conditional, c->det, brw_imm_f(0));
|
||||
if_insn = brw_IF(p, BRW_EXECUTE_4);
|
||||
{
|
||||
switch (c->nr_verts) {
|
||||
case 3: copy_bfc(c, c->vert[2]);
|
||||
case 2: copy_bfc(c, c->vert[1]);
|
||||
case 1: copy_bfc(c, c->vert[0]);
|
||||
}
|
||||
}
|
||||
brw_ENDIF(p, if_insn);
|
||||
brw_pop_insn_state(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Flat shading
|
||||
*/
|
||||
|
||||
#define VERT_RESULT_COLOR_BITS ((1<<VERT_RESULT_COL0) | \
|
||||
(1<<VERT_RESULT_COL1))
|
||||
|
||||
static void copy_colors( struct brw_sf_compile *c,
|
||||
struct brw_reg dst,
|
||||
struct brw_reg src)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
|
||||
if (c->key.attr_col0)
|
||||
brw_MOV(p,
|
||||
get_vert_attr(c, dst, c->key.attr_col0),
|
||||
get_vert_attr(c, src, c->key.attr_col0));
|
||||
|
||||
if (c->key.attr_col1)
|
||||
brw_MOV(p,
|
||||
get_vert_attr(c, dst, c->key.attr_col1),
|
||||
get_vert_attr(c, src, c->key.attr_col1));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Need to use a computed jump to copy flatshaded attributes as the
|
||||
* vertices are ordered according to y-coordinate before reaching this
|
||||
* point, so the PV could be anywhere.
|
||||
*/
|
||||
static void do_flatshade_triangle( struct brw_sf_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_reg ip = brw_ip_reg();
|
||||
GLuint jmpi = 1;
|
||||
GLuint nr = 0;
|
||||
|
||||
if (c->key.attr_col0)
|
||||
nr++;
|
||||
|
||||
if (c->key.attr_col1)
|
||||
nr++;
|
||||
|
||||
if (nr == 0)
|
||||
return;
|
||||
|
||||
/* Already done in clip program:
|
||||
*/
|
||||
if (c->key.primitive == SF_UNFILLED_TRIS)
|
||||
return;
|
||||
|
||||
if (BRW_IS_IGDNG(p->brw))
|
||||
jmpi = 2;
|
||||
|
||||
brw_push_insn_state(p);
|
||||
|
||||
brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr*2+1)));
|
||||
brw_JMPI(p, ip, ip, c->pv);
|
||||
|
||||
copy_colors(c, c->vert[1], c->vert[0]);
|
||||
copy_colors(c, c->vert[2], c->vert[0]);
|
||||
brw_JMPI(p, ip, ip, brw_imm_d(jmpi*(nr*4+1)));
|
||||
|
||||
copy_colors(c, c->vert[0], c->vert[1]);
|
||||
copy_colors(c, c->vert[2], c->vert[1]);
|
||||
brw_JMPI(p, ip, ip, brw_imm_d(jmpi*nr*2));
|
||||
|
||||
copy_colors(c, c->vert[0], c->vert[2]);
|
||||
copy_colors(c, c->vert[1], c->vert[2]);
|
||||
|
||||
brw_pop_insn_state(p);
|
||||
}
|
||||
|
||||
|
||||
static void do_flatshade_line( struct brw_sf_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_reg ip = brw_ip_reg();
|
||||
GLuint jmpi = 1;
|
||||
GLuint nr = 0;
|
||||
|
||||
if (c->key.attr_col0)
|
||||
nr++;
|
||||
|
||||
if (c->key.attr_col1)
|
||||
nr++;
|
||||
|
||||
if (nr == 0)
|
||||
return;
|
||||
|
||||
/* Already done in clip program:
|
||||
*/
|
||||
if (c->key.primitive == SF_UNFILLED_TRIS)
|
||||
return;
|
||||
|
||||
if (BRW_IS_IGDNG(p->brw))
|
||||
jmpi = 2;
|
||||
|
||||
brw_push_insn_state(p);
|
||||
|
||||
brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr+1)));
|
||||
brw_JMPI(p, ip, ip, c->pv);
|
||||
copy_colors(c, c->vert[1], c->vert[0]);
|
||||
|
||||
brw_JMPI(p, ip, ip, brw_imm_ud(jmpi*nr));
|
||||
copy_colors(c, c->vert[0], c->vert[1]);
|
||||
|
||||
brw_pop_insn_state(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Triangle setup.
|
||||
*/
|
||||
|
||||
|
||||
static void alloc_regs( struct brw_sf_compile *c )
|
||||
{
|
||||
GLuint reg, i;
|
||||
|
||||
/* Values computed by fixed function unit:
|
||||
*/
|
||||
c->pv = retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_D);
|
||||
c->det = brw_vec1_grf(1, 2);
|
||||
c->dx0 = brw_vec1_grf(1, 3);
|
||||
c->dx2 = brw_vec1_grf(1, 4);
|
||||
c->dy0 = brw_vec1_grf(1, 5);
|
||||
c->dy2 = brw_vec1_grf(1, 6);
|
||||
|
||||
/* z and 1/w passed in seperately:
|
||||
*/
|
||||
c->z[0] = brw_vec1_grf(2, 0);
|
||||
c->inv_w[0] = brw_vec1_grf(2, 1);
|
||||
c->z[1] = brw_vec1_grf(2, 2);
|
||||
c->inv_w[1] = brw_vec1_grf(2, 3);
|
||||
c->z[2] = brw_vec1_grf(2, 4);
|
||||
c->inv_w[2] = brw_vec1_grf(2, 5);
|
||||
|
||||
/* The vertices:
|
||||
*/
|
||||
reg = 3;
|
||||
for (i = 0; i < c->nr_verts; i++) {
|
||||
c->vert[i] = brw_vec8_grf(reg, 0);
|
||||
reg += c->nr_attr_regs;
|
||||
}
|
||||
|
||||
/* Temporaries, allocated after last vertex reg.
|
||||
*/
|
||||
c->inv_det = brw_vec1_grf(reg, 0); reg++;
|
||||
c->a1_sub_a0 = brw_vec8_grf(reg, 0); reg++;
|
||||
c->a2_sub_a0 = brw_vec8_grf(reg, 0); reg++;
|
||||
c->tmp = brw_vec8_grf(reg, 0); reg++;
|
||||
|
||||
/* Note grf allocation:
|
||||
*/
|
||||
c->prog_data.total_grf = reg;
|
||||
|
||||
|
||||
/* Outputs of this program - interpolation coefficients for
|
||||
* rasterization:
|
||||
*/
|
||||
c->m1Cx = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 1, 0);
|
||||
c->m2Cy = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 2, 0);
|
||||
c->m3C0 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 3, 0);
|
||||
}
|
||||
|
||||
|
||||
static void copy_z_inv_w( struct brw_sf_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
GLuint i;
|
||||
|
||||
brw_push_insn_state(p);
|
||||
|
||||
/* Copy both scalars with a single MOV:
|
||||
*/
|
||||
for (i = 0; i < c->nr_verts; i++)
|
||||
brw_MOV(p, vec2(suboffset(c->vert[i], 2)), vec2(c->z[i]));
|
||||
|
||||
brw_pop_insn_state(p);
|
||||
}
|
||||
|
||||
|
||||
static void invert_det( struct brw_sf_compile *c)
|
||||
{
|
||||
/* Looks like we invert all 8 elements just to get 1/det in
|
||||
* position 2 !?!
|
||||
*/
|
||||
brw_math(&c->func,
|
||||
c->inv_det,
|
||||
BRW_MATH_FUNCTION_INV,
|
||||
BRW_MATH_SATURATE_NONE,
|
||||
0,
|
||||
c->det,
|
||||
BRW_MATH_DATA_SCALAR,
|
||||
BRW_MATH_PRECISION_FULL);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Two attributes packed into a wide register. Figure out if either
|
||||
* or both of them need linear/perspective interpolation. Constant
|
||||
* regs are left as-is.
|
||||
*/
|
||||
static GLboolean calculate_masks( struct brw_sf_compile *c,
|
||||
GLuint reg,
|
||||
GLushort *pc,
|
||||
GLushort *pc_persp,
|
||||
GLushort *pc_linear)
|
||||
{
|
||||
GLboolean is_last_attr = (reg == c->nr_setup_regs - 1);
|
||||
GLuint persp_mask = c->key.persp_attrs;
|
||||
GLuint linear_mask = (c->key.persp_attrs | c->key.linear_attrs);
|
||||
|
||||
*pc_persp = 0;
|
||||
*pc_linear = 0;
|
||||
*pc = 0xf;
|
||||
|
||||
if (persp_mask & (1 << (reg*2)))
|
||||
*pc_persp = 0xf;
|
||||
|
||||
if (linear_mask & (1 << (reg*2)))
|
||||
*pc_linear = 0xf;
|
||||
|
||||
/* Maybe only processs one attribute on the final round:
|
||||
*/
|
||||
if (reg*2+1 < c->nr_setup_attrs) {
|
||||
*pc |= 0xf0;
|
||||
|
||||
if (persp_mask & (1 << (reg*2+1)))
|
||||
*pc_persp |= 0xf0;
|
||||
|
||||
if (linear_mask & (1 << (reg*2+1)))
|
||||
*pc_linear |= 0xf0;
|
||||
}
|
||||
|
||||
return is_last_attr;
|
||||
}
|
||||
|
||||
|
||||
void brw_emit_null_setup( struct brw_sf_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
|
||||
/* m0 is implicitly copied from r0 in the send instruction:
|
||||
*/
|
||||
brw_urb_WRITE(p,
|
||||
brw_null_reg(),
|
||||
0,
|
||||
brw_vec8_grf(0, 0), /* r0, will be copied to m0 */
|
||||
0, /* allocate */
|
||||
1, /* used */
|
||||
1, /* msg len */
|
||||
0, /* response len */
|
||||
1, /* eot */
|
||||
1, /* writes complete */
|
||||
0, /* offset */
|
||||
BRW_URB_SWIZZLE_TRANSPOSE);
|
||||
}
|
||||
|
||||
void brw_emit_tri_setup( struct brw_sf_compile *c, GLboolean allocate)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
GLuint i;
|
||||
|
||||
c->nr_verts = 3;
|
||||
|
||||
if (allocate)
|
||||
alloc_regs(c);
|
||||
|
||||
invert_det(c);
|
||||
copy_z_inv_w(c);
|
||||
|
||||
if (c->key.do_twoside_color)
|
||||
do_twoside_color(c);
|
||||
|
||||
if (c->key.do_flat_shading)
|
||||
do_flatshade_triangle(c);
|
||||
|
||||
|
||||
for (i = 0; i < c->nr_setup_regs; i++)
|
||||
{
|
||||
/* Pair of incoming attributes:
|
||||
*/
|
||||
struct brw_reg a0 = offset(c->vert[0], i);
|
||||
struct brw_reg a1 = offset(c->vert[1], i);
|
||||
struct brw_reg a2 = offset(c->vert[2], i);
|
||||
GLushort pc, pc_persp, pc_linear;
|
||||
GLboolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
|
||||
|
||||
if (pc_persp)
|
||||
{
|
||||
brw_set_predicate_control_flag_value(p, pc_persp);
|
||||
brw_MUL(p, a0, a0, c->inv_w[0]);
|
||||
brw_MUL(p, a1, a1, c->inv_w[1]);
|
||||
brw_MUL(p, a2, a2, c->inv_w[2]);
|
||||
}
|
||||
|
||||
|
||||
/* Calculate coefficients for interpolated values:
|
||||
*/
|
||||
if (pc_linear)
|
||||
{
|
||||
brw_set_predicate_control_flag_value(p, pc_linear);
|
||||
|
||||
brw_ADD(p, c->a1_sub_a0, a1, negate(a0));
|
||||
brw_ADD(p, c->a2_sub_a0, a2, negate(a0));
|
||||
|
||||
/* calculate dA/dx
|
||||
*/
|
||||
brw_MUL(p, brw_null_reg(), c->a1_sub_a0, c->dy2);
|
||||
brw_MAC(p, c->tmp, c->a2_sub_a0, negate(c->dy0));
|
||||
brw_MUL(p, c->m1Cx, c->tmp, c->inv_det);
|
||||
|
||||
/* calculate dA/dy
|
||||
*/
|
||||
brw_MUL(p, brw_null_reg(), c->a2_sub_a0, c->dx0);
|
||||
brw_MAC(p, c->tmp, c->a1_sub_a0, negate(c->dx2));
|
||||
brw_MUL(p, c->m2Cy, c->tmp, c->inv_det);
|
||||
}
|
||||
|
||||
{
|
||||
brw_set_predicate_control_flag_value(p, pc);
|
||||
/* start point for interpolation
|
||||
*/
|
||||
brw_MOV(p, c->m3C0, a0);
|
||||
|
||||
/* Copy m0..m3 to URB. m0 is implicitly copied from r0 in
|
||||
* the send instruction:
|
||||
*/
|
||||
brw_urb_WRITE(p,
|
||||
brw_null_reg(),
|
||||
0,
|
||||
brw_vec8_grf(0, 0), /* r0, will be copied to m0 */
|
||||
0, /* allocate */
|
||||
1, /* used */
|
||||
4, /* msg len */
|
||||
0, /* response len */
|
||||
last, /* eot */
|
||||
last, /* writes complete */
|
||||
i*4, /* offset */
|
||||
BRW_URB_SWIZZLE_TRANSPOSE); /* XXX: Swizzle control "SF to windower" */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void brw_emit_line_setup( struct brw_sf_compile *c, GLboolean allocate)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
GLuint i;
|
||||
|
||||
|
||||
c->nr_verts = 2;
|
||||
|
||||
if (allocate)
|
||||
alloc_regs(c);
|
||||
|
||||
invert_det(c);
|
||||
copy_z_inv_w(c);
|
||||
|
||||
if (c->key.do_flat_shading)
|
||||
do_flatshade_line(c);
|
||||
|
||||
for (i = 0; i < c->nr_setup_regs; i++)
|
||||
{
|
||||
/* Pair of incoming attributes:
|
||||
*/
|
||||
struct brw_reg a0 = offset(c->vert[0], i);
|
||||
struct brw_reg a1 = offset(c->vert[1], i);
|
||||
GLushort pc, pc_persp, pc_linear;
|
||||
GLboolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
|
||||
|
||||
if (pc_persp)
|
||||
{
|
||||
brw_set_predicate_control_flag_value(p, pc_persp);
|
||||
brw_MUL(p, a0, a0, c->inv_w[0]);
|
||||
brw_MUL(p, a1, a1, c->inv_w[1]);
|
||||
}
|
||||
|
||||
/* Calculate coefficients for position, color:
|
||||
*/
|
||||
if (pc_linear) {
|
||||
brw_set_predicate_control_flag_value(p, pc_linear);
|
||||
|
||||
brw_ADD(p, c->a1_sub_a0, a1, negate(a0));
|
||||
|
||||
brw_MUL(p, c->tmp, c->a1_sub_a0, c->dx0);
|
||||
brw_MUL(p, c->m1Cx, c->tmp, c->inv_det);
|
||||
|
||||
brw_MUL(p, c->tmp, c->a1_sub_a0, c->dy0);
|
||||
brw_MUL(p, c->m2Cy, c->tmp, c->inv_det);
|
||||
}
|
||||
|
||||
{
|
||||
brw_set_predicate_control_flag_value(p, pc);
|
||||
|
||||
/* start point for interpolation
|
||||
*/
|
||||
brw_MOV(p, c->m3C0, a0);
|
||||
|
||||
/* Copy m0..m3 to URB.
|
||||
*/
|
||||
brw_urb_WRITE(p,
|
||||
brw_null_reg(),
|
||||
0,
|
||||
brw_vec8_grf(0, 0),
|
||||
0, /* allocate */
|
||||
1, /* used */
|
||||
4, /* msg len */
|
||||
0, /* response len */
|
||||
last, /* eot */
|
||||
last, /* writes complete */
|
||||
i*4, /* urb destination offset */
|
||||
BRW_URB_SWIZZLE_TRANSPOSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void brw_emit_point_sprite_setup( struct brw_sf_compile *c, GLboolean allocate)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
GLuint i;
|
||||
|
||||
c->nr_verts = 1;
|
||||
|
||||
if (allocate)
|
||||
alloc_regs(c);
|
||||
|
||||
copy_z_inv_w(c);
|
||||
|
||||
for (i = 0; i < c->nr_setup_regs; i++)
|
||||
{
|
||||
/* XXX: only seems to check point_coord_replace_attrs for every
|
||||
* second attribute?!?
|
||||
*/
|
||||
boolean coord_replace = !!(c->key.point_coord_replace_attrs & (1<<(2*i)));
|
||||
struct brw_reg a0 = offset(c->vert[0], i);
|
||||
GLushort pc, pc_persp, pc_linear;
|
||||
GLboolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
|
||||
|
||||
if (pc_persp)
|
||||
{
|
||||
if (coord_replace) {
|
||||
brw_set_predicate_control_flag_value(p, pc_persp);
|
||||
brw_MUL(p, a0, a0, c->inv_w[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (coord_replace) {
|
||||
/* Caculate 1.0/PointWidth */
|
||||
brw_math(&c->func,
|
||||
c->tmp,
|
||||
BRW_MATH_FUNCTION_INV,
|
||||
BRW_MATH_SATURATE_NONE,
|
||||
0,
|
||||
c->dx0,
|
||||
BRW_MATH_DATA_SCALAR,
|
||||
BRW_MATH_PRECISION_FULL);
|
||||
|
||||
if (c->key.sprite_origin_lower_left) {
|
||||
brw_MUL(p, c->m1Cx, c->tmp, c->inv_w[0]);
|
||||
brw_MOV(p, vec1(suboffset(c->m1Cx, 1)), brw_imm_f(0.0));
|
||||
brw_MUL(p, c->m2Cy, c->tmp, negate(c->inv_w[0]));
|
||||
brw_MOV(p, vec1(suboffset(c->m2Cy, 0)), brw_imm_f(0.0));
|
||||
}
|
||||
else {
|
||||
brw_MUL(p, c->m1Cx, c->tmp, c->inv_w[0]);
|
||||
brw_MOV(p, vec1(suboffset(c->m1Cx, 1)), brw_imm_f(0.0));
|
||||
brw_MUL(p, c->m2Cy, c->tmp, c->inv_w[0]);
|
||||
brw_MOV(p, vec1(suboffset(c->m2Cy, 0)), brw_imm_f(0.0));
|
||||
}
|
||||
}
|
||||
else {
|
||||
brw_MOV(p, c->m1Cx, brw_imm_ud(0));
|
||||
brw_MOV(p, c->m2Cy, brw_imm_ud(0));
|
||||
}
|
||||
|
||||
{
|
||||
brw_set_predicate_control_flag_value(p, pc);
|
||||
if (coord_replace) {
|
||||
if (c->key.sprite_origin_lower_left) {
|
||||
brw_MUL(p, c->m3C0, c->inv_w[0], brw_imm_f(1.0));
|
||||
brw_MOV(p, vec1(suboffset(c->m3C0, 0)), brw_imm_f(0.0));
|
||||
}
|
||||
else {
|
||||
brw_MOV(p, c->m3C0, brw_imm_f(0.0));
|
||||
}
|
||||
}
|
||||
else {
|
||||
brw_MOV(p, c->m3C0, a0); /* constant value */
|
||||
}
|
||||
|
||||
/* Copy m0..m3 to URB.
|
||||
*/
|
||||
brw_urb_WRITE(p,
|
||||
brw_null_reg(),
|
||||
0,
|
||||
brw_vec8_grf(0, 0),
|
||||
0, /* allocate */
|
||||
1, /* used */
|
||||
4, /* msg len */
|
||||
0, /* response len */
|
||||
last, /* eot */
|
||||
last, /* writes complete */
|
||||
i*4, /* urb destination offset */
|
||||
BRW_URB_SWIZZLE_TRANSPOSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Points setup - several simplifications as all attributes are
|
||||
* constant across the face of the point (point sprites excluded!)
|
||||
*/
|
||||
void brw_emit_point_setup( struct brw_sf_compile *c, GLboolean allocate)
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
GLuint i;
|
||||
|
||||
c->nr_verts = 1;
|
||||
|
||||
if (allocate)
|
||||
alloc_regs(c);
|
||||
|
||||
copy_z_inv_w(c);
|
||||
|
||||
brw_MOV(p, c->m1Cx, brw_imm_ud(0)); /* zero - move out of loop */
|
||||
brw_MOV(p, c->m2Cy, brw_imm_ud(0)); /* zero - move out of loop */
|
||||
|
||||
for (i = 0; i < c->nr_setup_regs; i++)
|
||||
{
|
||||
struct brw_reg a0 = offset(c->vert[0], i);
|
||||
GLushort pc, pc_persp, pc_linear;
|
||||
GLboolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
|
||||
|
||||
if (pc_persp)
|
||||
{
|
||||
/* This seems odd as the values are all constant, but the
|
||||
* fragment shader will be expecting it:
|
||||
*/
|
||||
brw_set_predicate_control_flag_value(p, pc_persp);
|
||||
brw_MUL(p, a0, a0, c->inv_w[0]);
|
||||
}
|
||||
|
||||
|
||||
/* The delta values are always zero, just send the starting
|
||||
* coordinate. Again, this is to fit in with the interpolation
|
||||
* code in the fragment shader.
|
||||
*/
|
||||
{
|
||||
brw_set_predicate_control_flag_value(p, pc);
|
||||
|
||||
brw_MOV(p, c->m3C0, a0); /* constant value */
|
||||
|
||||
/* Copy m0..m3 to URB.
|
||||
*/
|
||||
brw_urb_WRITE(p,
|
||||
brw_null_reg(),
|
||||
0,
|
||||
brw_vec8_grf(0, 0),
|
||||
0, /* allocate */
|
||||
1, /* used */
|
||||
4, /* msg len */
|
||||
0, /* response len */
|
||||
last, /* eot */
|
||||
last, /* writes complete */
|
||||
i*4, /* urb destination offset */
|
||||
BRW_URB_SWIZZLE_TRANSPOSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void brw_emit_anyprim_setup( struct brw_sf_compile *c )
|
||||
{
|
||||
struct brw_compile *p = &c->func;
|
||||
struct brw_reg ip = brw_ip_reg();
|
||||
struct brw_reg payload_prim = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, 1, 0);
|
||||
struct brw_reg payload_attr = get_element_ud(brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, 1, 0), 0);
|
||||
struct brw_reg primmask;
|
||||
struct brw_instruction *jmp;
|
||||
struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD));
|
||||
|
||||
GLuint saveflag;
|
||||
|
||||
c->nr_verts = 3;
|
||||
alloc_regs(c);
|
||||
|
||||
primmask = retype(get_element(c->tmp, 0), BRW_REGISTER_TYPE_UD);
|
||||
|
||||
brw_MOV(p, primmask, brw_imm_ud(1));
|
||||
brw_SHL(p, primmask, primmask, payload_prim);
|
||||
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
|
||||
brw_AND(p, v1_null_ud, primmask, brw_imm_ud((1<<_3DPRIM_TRILIST) |
|
||||
(1<<_3DPRIM_TRISTRIP) |
|
||||
(1<<_3DPRIM_TRIFAN) |
|
||||
(1<<_3DPRIM_TRISTRIP_REVERSE) |
|
||||
(1<<_3DPRIM_POLYGON) |
|
||||
(1<<_3DPRIM_RECTLIST) |
|
||||
(1<<_3DPRIM_TRIFAN_NOSTIPPLE)));
|
||||
jmp = brw_JMPI(p, ip, ip, brw_imm_d(0));
|
||||
{
|
||||
saveflag = p->flag_value;
|
||||
brw_push_insn_state(p);
|
||||
brw_emit_tri_setup( c, GL_FALSE );
|
||||
brw_pop_insn_state(p);
|
||||
p->flag_value = saveflag;
|
||||
/* note - thread killed in subroutine, so must
|
||||
* restore the flag which is changed when building
|
||||
* the subroutine. fix #13240
|
||||
*/
|
||||
}
|
||||
brw_land_fwd_jump(p, jmp);
|
||||
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
|
||||
brw_AND(p, v1_null_ud, primmask, brw_imm_ud((1<<_3DPRIM_LINELIST) |
|
||||
(1<<_3DPRIM_LINESTRIP) |
|
||||
(1<<_3DPRIM_LINELOOP) |
|
||||
(1<<_3DPRIM_LINESTRIP_CONT) |
|
||||
(1<<_3DPRIM_LINESTRIP_BF) |
|
||||
(1<<_3DPRIM_LINESTRIP_CONT_BF)));
|
||||
jmp = brw_JMPI(p, ip, ip, brw_imm_d(0));
|
||||
{
|
||||
saveflag = p->flag_value;
|
||||
brw_push_insn_state(p);
|
||||
brw_emit_line_setup( c, GL_FALSE );
|
||||
brw_pop_insn_state(p);
|
||||
p->flag_value = saveflag;
|
||||
/* note - thread killed in subroutine */
|
||||
}
|
||||
brw_land_fwd_jump(p, jmp);
|
||||
|
||||
brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
|
||||
brw_AND(p, v1_null_ud, payload_attr, brw_imm_ud(1<<BRW_SPRITE_POINT_ENABLE));
|
||||
jmp = brw_JMPI(p, ip, ip, brw_imm_d(0));
|
||||
{
|
||||
saveflag = p->flag_value;
|
||||
brw_push_insn_state(p);
|
||||
brw_emit_point_sprite_setup( c, GL_FALSE );
|
||||
brw_pop_insn_state(p);
|
||||
p->flag_value = saveflag;
|
||||
}
|
||||
brw_land_fwd_jump(p, jmp);
|
||||
|
||||
brw_emit_point_setup( c, GL_FALSE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_debug.h"
|
||||
#include "brw_pipe_rast.h"
|
||||
|
||||
static enum pipe_error upload_sf_vp(struct brw_context *brw)
|
||||
{
|
||||
const struct pipe_viewport_state *vp = &brw->curr.viewport;
|
||||
const struct pipe_scissor_state *scissor = &brw->curr.scissor;
|
||||
struct brw_sf_viewport sfv;
|
||||
enum pipe_error ret;
|
||||
|
||||
memset(&sfv, 0, sizeof(sfv));
|
||||
|
||||
/* PIPE_NEW_VIEWPORT, PIPE_NEW_SCISSOR */
|
||||
|
||||
sfv.viewport.m00 = vp->scale[0];
|
||||
sfv.viewport.m11 = vp->scale[1];
|
||||
sfv.viewport.m22 = vp->scale[2];
|
||||
sfv.viewport.m30 = vp->translate[0];
|
||||
sfv.viewport.m31 = vp->translate[1];
|
||||
sfv.viewport.m32 = vp->translate[2];
|
||||
|
||||
sfv.scissor.xmin = scissor->minx;
|
||||
sfv.scissor.xmax = scissor->maxx - 1; /* ? */
|
||||
sfv.scissor.ymin = scissor->miny;
|
||||
sfv.scissor.ymax = scissor->maxy - 1; /* ? */
|
||||
|
||||
ret = brw_cache_data( &brw->cache, BRW_SF_VP, &sfv, NULL, 0,
|
||||
&brw->sf.vp_bo );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_sf_vp = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_VIEWPORT |
|
||||
PIPE_NEW_SCISSOR),
|
||||
.brw = 0,
|
||||
.cache = 0
|
||||
},
|
||||
.prepare = upload_sf_vp
|
||||
};
|
||||
|
||||
struct brw_sf_unit_key {
|
||||
unsigned int total_grf;
|
||||
unsigned int urb_entry_read_length;
|
||||
unsigned int nr_urb_entries, urb_size, sfsize;
|
||||
|
||||
unsigned scissor:1;
|
||||
unsigned line_smooth:1;
|
||||
unsigned point_sprite:1;
|
||||
unsigned point_attenuated:1;
|
||||
unsigned front_face:2;
|
||||
unsigned cull_mode:2;
|
||||
unsigned flatshade_first:1;
|
||||
unsigned gl_rasterization_rules:1;
|
||||
unsigned line_last_pixel_enable:1;
|
||||
float line_width;
|
||||
float point_size;
|
||||
};
|
||||
|
||||
static void
|
||||
sf_unit_populate_key(struct brw_context *brw, struct brw_sf_unit_key *key)
|
||||
{
|
||||
const struct pipe_rasterizer_state *rast = &brw->curr.rast->templ;
|
||||
memset(key, 0, sizeof(*key));
|
||||
|
||||
/* CACHE_NEW_SF_PROG */
|
||||
key->total_grf = brw->sf.prog_data->total_grf;
|
||||
key->urb_entry_read_length = brw->sf.prog_data->urb_read_length;
|
||||
|
||||
/* BRW_NEW_URB_FENCE */
|
||||
key->nr_urb_entries = brw->urb.nr_sf_entries;
|
||||
key->urb_size = brw->urb.vsize;
|
||||
key->sfsize = brw->urb.sfsize;
|
||||
|
||||
/* PIPE_NEW_RAST */
|
||||
key->scissor = rast->scissor;
|
||||
key->front_face = rast->front_winding;
|
||||
key->cull_mode = rast->cull_mode;
|
||||
key->line_smooth = rast->line_smooth;
|
||||
key->line_width = rast->line_width;
|
||||
key->flatshade_first = rast->flatshade_first;
|
||||
key->line_last_pixel_enable = rast->line_last_pixel;
|
||||
key->gl_rasterization_rules = rast->gl_rasterization_rules;
|
||||
|
||||
key->point_sprite = rast->point_sprite;
|
||||
key->point_attenuated = rast->point_size_per_vertex;
|
||||
|
||||
key->point_size = CLAMP(rast->point_size,
|
||||
rast->point_size_min,
|
||||
rast->point_size_max);
|
||||
}
|
||||
|
||||
static enum pipe_error
|
||||
sf_unit_create_from_key(struct brw_context *brw,
|
||||
struct brw_sf_unit_key *key,
|
||||
struct brw_winsys_reloc *reloc,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
struct brw_sf_unit_state sf;
|
||||
enum pipe_error ret;
|
||||
int chipset_max_threads;
|
||||
memset(&sf, 0, sizeof(sf));
|
||||
|
||||
sf.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
|
||||
/* reloc */
|
||||
sf.thread0.kernel_start_pointer = 0;
|
||||
|
||||
sf.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
|
||||
|
||||
sf.thread3.dispatch_grf_start_reg = 3;
|
||||
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
sf.thread3.urb_entry_read_offset = 3;
|
||||
else
|
||||
sf.thread3.urb_entry_read_offset = 1;
|
||||
|
||||
sf.thread3.urb_entry_read_length = key->urb_entry_read_length;
|
||||
|
||||
sf.thread4.nr_urb_entries = key->nr_urb_entries;
|
||||
sf.thread4.urb_entry_allocation_size = key->sfsize - 1;
|
||||
|
||||
/* Each SF thread produces 1 PUE, and there can be up to 24(Pre-IGDNG) or
|
||||
* 48(IGDNG) threads
|
||||
*/
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
chipset_max_threads = 48;
|
||||
else
|
||||
chipset_max_threads = 24;
|
||||
|
||||
sf.thread4.max_threads = MIN2(chipset_max_threads, key->nr_urb_entries) - 1;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_SINGLE_THREAD)
|
||||
sf.thread4.max_threads = 0;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_STATS)
|
||||
sf.thread4.stats_enable = 1;
|
||||
|
||||
/* CACHE_NEW_SF_VP */
|
||||
/* reloc */
|
||||
sf.sf5.sf_viewport_state_offset = 0;
|
||||
|
||||
sf.sf5.viewport_transform = 1;
|
||||
|
||||
if (key->scissor)
|
||||
sf.sf6.scissor = 1;
|
||||
|
||||
if (key->front_face == PIPE_WINDING_CCW)
|
||||
sf.sf5.front_winding = BRW_FRONTWINDING_CCW;
|
||||
else
|
||||
sf.sf5.front_winding = BRW_FRONTWINDING_CW;
|
||||
|
||||
switch (key->cull_mode) {
|
||||
case PIPE_WINDING_CCW:
|
||||
case PIPE_WINDING_CW:
|
||||
sf.sf6.cull_mode = (key->front_face == key->cull_mode ?
|
||||
BRW_CULLMODE_FRONT :
|
||||
BRW_CULLMODE_BACK);
|
||||
break;
|
||||
case PIPE_WINDING_BOTH:
|
||||
sf.sf6.cull_mode = BRW_CULLMODE_BOTH;
|
||||
break;
|
||||
case PIPE_WINDING_NONE:
|
||||
sf.sf6.cull_mode = BRW_CULLMODE_NONE;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
sf.sf6.cull_mode = BRW_CULLMODE_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* _NEW_LINE */
|
||||
/* XXX use ctx->Const.Min/MaxLineWidth here */
|
||||
sf.sf6.line_width = CLAMP(key->line_width, 1.0, 5.0) * (1<<1);
|
||||
|
||||
sf.sf6.line_endcap_aa_region_width = 1;
|
||||
if (key->line_smooth)
|
||||
sf.sf6.aa_enable = 1;
|
||||
else if (sf.sf6.line_width <= 0x2)
|
||||
sf.sf6.line_width = 0;
|
||||
|
||||
/* XXX: gl_rasterization_rules? something else?
|
||||
*/
|
||||
sf.sf6.point_rast_rule = BRW_RASTRULE_UPPER_RIGHT;
|
||||
sf.sf6.point_rast_rule = BRW_RASTRULE_LOWER_RIGHT;
|
||||
sf.sf6.point_rast_rule = 1;
|
||||
|
||||
/* XXX clamp max depends on AA vs. non-AA */
|
||||
|
||||
/* _NEW_POINT */
|
||||
sf.sf7.sprite_point = key->point_sprite;
|
||||
sf.sf7.point_size = CLAMP(rint(key->point_size), 1, 255) * (1<<3);
|
||||
sf.sf7.use_point_size_state = !key->point_attenuated;
|
||||
sf.sf7.aa_line_distance_mode = 0;
|
||||
|
||||
/* might be BRW_NEW_PRIMITIVE if we have to adjust pv for polygons:
|
||||
*/
|
||||
if (!key->flatshade_first) {
|
||||
sf.sf7.trifan_pv = 2;
|
||||
sf.sf7.linestrip_pv = 1;
|
||||
sf.sf7.tristrip_pv = 2;
|
||||
} else {
|
||||
sf.sf7.trifan_pv = 1;
|
||||
sf.sf7.linestrip_pv = 0;
|
||||
sf.sf7.tristrip_pv = 0;
|
||||
}
|
||||
|
||||
sf.sf7.line_last_pixel_enable = key->line_last_pixel_enable;
|
||||
|
||||
/* Set bias for OpenGL rasterization rules:
|
||||
*/
|
||||
if (key->gl_rasterization_rules) {
|
||||
sf.sf6.dest_org_vbias = 0x8;
|
||||
sf.sf6.dest_org_hbias = 0x8;
|
||||
}
|
||||
else {
|
||||
sf.sf6.dest_org_vbias = 0x0;
|
||||
sf.sf6.dest_org_hbias = 0x0;
|
||||
}
|
||||
|
||||
ret = brw_upload_cache(&brw->cache, BRW_SF_UNIT,
|
||||
key, sizeof(*key),
|
||||
reloc, 2,
|
||||
&sf, sizeof(sf),
|
||||
NULL, NULL,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
static enum pipe_error upload_sf_unit( struct brw_context *brw )
|
||||
{
|
||||
struct brw_sf_unit_key key;
|
||||
struct brw_winsys_reloc reloc[2];
|
||||
unsigned total_grf;
|
||||
unsigned viewport_transform;
|
||||
unsigned front_winding;
|
||||
enum pipe_error ret;
|
||||
|
||||
sf_unit_populate_key(brw, &key);
|
||||
|
||||
/* XXX: cut this crap and pre calculate the key:
|
||||
*/
|
||||
total_grf = (align(key.total_grf, 16) / 16 - 1);
|
||||
viewport_transform = 1;
|
||||
front_winding = (key.front_face == PIPE_WINDING_CCW ?
|
||||
BRW_FRONTWINDING_CCW :
|
||||
BRW_FRONTWINDING_CW);
|
||||
|
||||
/* Emit SF program relocation */
|
||||
make_reloc(&reloc[0],
|
||||
BRW_USAGE_STATE,
|
||||
total_grf << 1,
|
||||
offsetof(struct brw_sf_unit_state, thread0),
|
||||
brw->sf.prog_bo);
|
||||
|
||||
/* Emit SF viewport relocation */
|
||||
make_reloc(&reloc[1],
|
||||
BRW_USAGE_STATE,
|
||||
front_winding | (viewport_transform << 1),
|
||||
offsetof(struct brw_sf_unit_state, sf5),
|
||||
brw->sf.vp_bo);
|
||||
|
||||
|
||||
if (brw_search_cache(&brw->cache, BRW_SF_UNIT,
|
||||
&key, sizeof(key),
|
||||
reloc, 2,
|
||||
NULL,
|
||||
&brw->sf.state_bo))
|
||||
return PIPE_OK;
|
||||
|
||||
|
||||
ret = sf_unit_create_from_key(brw, &key,
|
||||
reloc,
|
||||
&brw->sf.state_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_sf_unit = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_RAST),
|
||||
.brw = BRW_NEW_URB_FENCE,
|
||||
.cache = (CACHE_NEW_SF_VP |
|
||||
CACHE_NEW_SF_PROG)
|
||||
},
|
||||
.prepare = upload_sf_unit,
|
||||
};
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BRW_STATE_H
|
||||
#define BRW_STATE_H
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
|
||||
static INLINE void
|
||||
brw_add_validated_bo(struct brw_context *brw, struct brw_winsys_buffer *bo)
|
||||
{
|
||||
assert(brw->state.validated_bo_count < Elements(brw->state.validated_bos));
|
||||
|
||||
if (bo != NULL) {
|
||||
bo_reference( &brw->state.validated_bos[brw->state.validated_bo_count++],
|
||||
bo );
|
||||
}
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_blend_constant_color;
|
||||
const struct brw_tracked_state brw_cc_unit;
|
||||
const struct brw_tracked_state brw_cc_vp;
|
||||
const struct brw_tracked_state brw_clip_prog;
|
||||
const struct brw_tracked_state brw_clip_unit;
|
||||
const struct brw_tracked_state brw_curbe_buffer;
|
||||
const struct brw_tracked_state brw_curbe_offsets;
|
||||
const struct brw_tracked_state brw_invarient_state;
|
||||
const struct brw_tracked_state brw_gs_prog;
|
||||
const struct brw_tracked_state brw_gs_unit;
|
||||
const struct brw_tracked_state brw_line_stipple;
|
||||
const struct brw_tracked_state brw_aa_line_parameters;
|
||||
const struct brw_tracked_state brw_pipelined_state_pointers;
|
||||
const struct brw_tracked_state brw_binding_table_pointers;
|
||||
const struct brw_tracked_state brw_depthbuffer;
|
||||
const struct brw_tracked_state brw_polygon_stipple;
|
||||
const struct brw_tracked_state brw_program_parameters;
|
||||
const struct brw_tracked_state brw_recalculate_urb_fence;
|
||||
const struct brw_tracked_state brw_sf_prog;
|
||||
const struct brw_tracked_state brw_sf_unit;
|
||||
const struct brw_tracked_state brw_sf_vp;
|
||||
const struct brw_tracked_state brw_state_base_address;
|
||||
const struct brw_tracked_state brw_urb_fence;
|
||||
const struct brw_tracked_state brw_vertex_state;
|
||||
const struct brw_tracked_state brw_vs_surfaces;
|
||||
const struct brw_tracked_state brw_vs_prog;
|
||||
const struct brw_tracked_state brw_vs_unit;
|
||||
const struct brw_tracked_state brw_wm_input_sizes;
|
||||
const struct brw_tracked_state brw_wm_prog;
|
||||
const struct brw_tracked_state brw_wm_samplers;
|
||||
const struct brw_tracked_state brw_wm_constant_surface;
|
||||
const struct brw_tracked_state brw_wm_surfaces;
|
||||
const struct brw_tracked_state brw_wm_unit;
|
||||
|
||||
const struct brw_tracked_state brw_psp_urb_cbs;
|
||||
|
||||
const struct brw_tracked_state brw_pipe_control;
|
||||
|
||||
const struct brw_tracked_state brw_drawing_rect;
|
||||
const struct brw_tracked_state brw_indices;
|
||||
const struct brw_tracked_state brw_vertices;
|
||||
const struct brw_tracked_state brw_index_buffer;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* brw_state.c
|
||||
*/
|
||||
int brw_validate_state(struct brw_context *brw);
|
||||
int brw_upload_state(struct brw_context *brw);
|
||||
void brw_init_state(struct brw_context *brw);
|
||||
void brw_destroy_state(struct brw_context *brw);
|
||||
|
||||
/***********************************************************************
|
||||
* brw_state_cache.c
|
||||
*/
|
||||
enum pipe_error brw_cache_data(struct brw_cache *cache,
|
||||
enum brw_cache_id cache_id,
|
||||
const void *data,
|
||||
struct brw_winsys_reloc *relocs,
|
||||
GLuint nr_relocs,
|
||||
struct brw_winsys_buffer **bo_out );
|
||||
|
||||
enum pipe_error brw_cache_data_sz(struct brw_cache *cache,
|
||||
enum brw_cache_id cache_id,
|
||||
const void *data,
|
||||
GLuint data_size,
|
||||
struct brw_winsys_reloc *relocs,
|
||||
GLuint nr_relocs,
|
||||
struct brw_winsys_buffer **bo_out);
|
||||
|
||||
enum pipe_error brw_upload_cache( struct brw_cache *cache,
|
||||
enum brw_cache_id cache_id,
|
||||
const void *key,
|
||||
GLuint key_sz,
|
||||
struct brw_winsys_reloc *relocs,
|
||||
GLuint nr_relocs,
|
||||
const void *data,
|
||||
GLuint data_sz,
|
||||
const void *aux,
|
||||
void *aux_return ,
|
||||
struct brw_winsys_buffer **bo_out);
|
||||
|
||||
boolean brw_search_cache( struct brw_cache *cache,
|
||||
enum brw_cache_id cache_id,
|
||||
const void *key,
|
||||
GLuint key_size,
|
||||
struct brw_winsys_reloc *relocs,
|
||||
GLuint nr_relocs,
|
||||
void *aux_return,
|
||||
struct brw_winsys_buffer **bo_out);
|
||||
|
||||
void brw_state_cache_check_size( struct brw_context *brw );
|
||||
|
||||
void brw_init_caches( struct brw_context *brw );
|
||||
void brw_destroy_caches( struct brw_context *brw );
|
||||
void brw_state_cache_bo_delete(struct brw_cache *cache, struct brw_winsys_buffer *bo);
|
||||
|
||||
/***********************************************************************
|
||||
* brw_state_batch.c
|
||||
*/
|
||||
#define BRW_BATCH_STRUCT(brw, s) brw_batchbuffer_data( brw->batch, (s), sizeof(*(s)), IGNORE_CLIPRECTS)
|
||||
#define BRW_CACHED_BATCH_STRUCT(brw, s) brw_cached_batch_struct( brw, (s), sizeof(*(s)) )
|
||||
|
||||
GLboolean brw_cached_batch_struct( struct brw_context *brw,
|
||||
const void *data,
|
||||
GLuint sz );
|
||||
void brw_destroy_batch_cache( struct brw_context *brw );
|
||||
void brw_clear_batch_cache( struct brw_context *brw );
|
||||
|
||||
/***********************************************************************
|
||||
* brw_wm_surface_state.c
|
||||
*/
|
||||
|
||||
/***********************************************************************
|
||||
* brw_state_debug.c
|
||||
*/
|
||||
void brw_update_dirty_counts( unsigned mesa,
|
||||
unsigned brw,
|
||||
unsigned cache );
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "brw_state.h"
|
||||
#include "brw_batchbuffer.h"
|
||||
|
||||
|
||||
|
||||
/* A facility similar to the data caching code above, which aims to
|
||||
* prevent identical commands being issued repeatedly.
|
||||
*/
|
||||
GLboolean brw_cached_batch_struct( struct brw_context *brw,
|
||||
const void *data,
|
||||
GLuint sz )
|
||||
{
|
||||
struct brw_cached_batch_item *item = brw->cached_batch_items;
|
||||
struct header *newheader = (struct header *)data;
|
||||
|
||||
if (brw->flags.always_emit_state) {
|
||||
brw_batchbuffer_data(brw->batch, data, sz, IGNORE_CLIPRECTS);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
while (item) {
|
||||
if (item->header->opcode == newheader->opcode) {
|
||||
if (item->sz == sz && memcmp(item->header, newheader, sz) == 0)
|
||||
return GL_FALSE;
|
||||
if (item->sz != sz) {
|
||||
FREE(item->header);
|
||||
item->header = MALLOC(sz);
|
||||
item->sz = sz;
|
||||
}
|
||||
goto emit;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
assert(!item);
|
||||
item = CALLOC_STRUCT(brw_cached_batch_item);
|
||||
item->header = MALLOC(sz);
|
||||
item->sz = sz;
|
||||
item->next = brw->cached_batch_items;
|
||||
brw->cached_batch_items = item;
|
||||
|
||||
emit:
|
||||
memcpy(item->header, newheader, sz);
|
||||
brw_batchbuffer_data(brw->batch, data, sz, IGNORE_CLIPRECTS);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
void brw_clear_batch_cache( struct brw_context *brw )
|
||||
{
|
||||
struct brw_cached_batch_item *item = brw->cached_batch_items;
|
||||
|
||||
while (item) {
|
||||
struct brw_cached_batch_item *next = item->next;
|
||||
free((void *)item->header);
|
||||
free(item);
|
||||
item = next;
|
||||
}
|
||||
|
||||
brw->cached_batch_items = NULL;
|
||||
}
|
||||
|
||||
void brw_destroy_batch_cache( struct brw_context *brw )
|
||||
{
|
||||
brw_clear_batch_cache(brw);
|
||||
}
|
||||
@@ -0,0 +1,617 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
/** @file brw_state_cache.c
|
||||
*
|
||||
* This file implements a simple static state cache for 965. The consumers
|
||||
* can query the hash table of state using a cache_id, opaque key data,
|
||||
* and list of buffers that will be used in relocations, and receive the
|
||||
* corresponding state buffer object of state (plus associated auxiliary
|
||||
* data) in return.
|
||||
*
|
||||
* The inner workings are a simple hash table based on a CRC of the key data.
|
||||
* The cache_id and relocation target buffers associated with the state
|
||||
* buffer are included as auxiliary key data, but are not part of the hash
|
||||
* value (this should be fixed, but will likely be fixed instead by making
|
||||
* consumers use structured keys).
|
||||
*
|
||||
* Replacement is not implemented. Instead, when the cache gets too big, at
|
||||
* a safe point (unlock) we throw out all of the cache data and let it
|
||||
* regenerate for the next rendering operation.
|
||||
*
|
||||
* The reloc structs need to be included as key data, otherwise the
|
||||
* non-unique values stuffed in the offset in key data through
|
||||
* brw_cache_data() may result in successful probe for state buffers
|
||||
* even when the buffer being referenced doesn't match. The result would be
|
||||
* that the same state cache entry is used twice for different buffers,
|
||||
* only one of the two buffers referenced gets put into the offset, and the
|
||||
* incorrect program is run for the other instance.
|
||||
*/
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "brw_debug.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_batchbuffer.h"
|
||||
|
||||
/* XXX: Fixme - have to include these to get the sizes of the prog_key
|
||||
* structs:
|
||||
*/
|
||||
#include "brw_wm.h"
|
||||
#include "brw_vs.h"
|
||||
#include "brw_clip.h"
|
||||
#include "brw_sf.h"
|
||||
#include "brw_gs.h"
|
||||
|
||||
|
||||
static GLuint
|
||||
hash_key(const void *key, GLuint key_size,
|
||||
struct brw_winsys_reloc *relocs, GLuint nr_relocs)
|
||||
{
|
||||
GLuint *ikey = (GLuint *)key;
|
||||
GLuint hash = 0, i;
|
||||
|
||||
assert(key_size % 4 == 0);
|
||||
|
||||
/* I'm sure this can be improved on:
|
||||
*/
|
||||
for (i = 0; i < key_size/4; i++) {
|
||||
hash ^= ikey[i];
|
||||
hash = (hash << 5) | (hash >> 27);
|
||||
}
|
||||
|
||||
/* Include the BO pointers as key data as well */
|
||||
ikey = (GLuint *)relocs;
|
||||
key_size = nr_relocs * sizeof(struct brw_winsys_reloc);
|
||||
for (i = 0; i < key_size/4; i++) {
|
||||
hash ^= ikey[i];
|
||||
hash = (hash << 5) | (hash >> 27);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Marks a new buffer as being chosen for the given cache id.
|
||||
*/
|
||||
static void
|
||||
update_cache_last(struct brw_cache *cache, enum brw_cache_id cache_id,
|
||||
struct brw_winsys_buffer *bo)
|
||||
{
|
||||
if (bo == cache->last_bo[cache_id])
|
||||
return; /* no change */
|
||||
|
||||
bo_reference( &cache->last_bo[cache_id], bo );
|
||||
|
||||
cache->brw->state.dirty.cache |= 1 << cache_id;
|
||||
}
|
||||
|
||||
|
||||
static struct brw_cache_item *
|
||||
search_cache(struct brw_cache *cache, enum brw_cache_id cache_id,
|
||||
GLuint hash, const void *key, GLuint key_size,
|
||||
struct brw_winsys_reloc *relocs, GLuint nr_relocs)
|
||||
{
|
||||
struct brw_cache_item *c;
|
||||
|
||||
#if 0
|
||||
int bucketcount = 0;
|
||||
|
||||
for (c = cache->items[hash % cache->size]; c; c = c->next)
|
||||
bucketcount++;
|
||||
|
||||
debug_printf("bucket %d/%d = %d/%d items\n", hash % cache->size,
|
||||
cache->size, bucketcount, cache->n_items);
|
||||
#endif
|
||||
|
||||
for (c = cache->items[hash % cache->size]; c; c = c->next) {
|
||||
if (c->cache_id == cache_id &&
|
||||
c->hash == hash &&
|
||||
c->key_size == key_size &&
|
||||
memcmp(c->key, key, key_size) == 0 &&
|
||||
c->nr_relocs == nr_relocs &&
|
||||
memcmp(c->relocs, relocs, nr_relocs * sizeof *relocs) == 0)
|
||||
return c;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
rehash(struct brw_cache *cache)
|
||||
{
|
||||
struct brw_cache_item **items;
|
||||
struct brw_cache_item *c, *next;
|
||||
GLuint size, i;
|
||||
|
||||
size = cache->size * 3;
|
||||
items = (struct brw_cache_item**) CALLOC(size, sizeof(*items));
|
||||
|
||||
for (i = 0; i < cache->size; i++)
|
||||
for (c = cache->items[i]; c; c = next) {
|
||||
next = c->next;
|
||||
c->next = items[c->hash % size];
|
||||
items[c->hash % size] = c;
|
||||
}
|
||||
|
||||
FREE(cache->items);
|
||||
cache->items = items;
|
||||
cache->size = size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the buffer object matching cache_id and key, or NULL.
|
||||
*/
|
||||
boolean
|
||||
brw_search_cache(struct brw_cache *cache,
|
||||
enum brw_cache_id cache_id,
|
||||
const void *key,
|
||||
GLuint key_size,
|
||||
struct brw_winsys_reloc *relocs,
|
||||
GLuint nr_relocs,
|
||||
void *aux_return,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
struct brw_cache_item *item;
|
||||
GLuint hash = hash_key(key, key_size, relocs, nr_relocs);
|
||||
|
||||
item = search_cache(cache, cache_id, hash, key, key_size,
|
||||
relocs, nr_relocs);
|
||||
|
||||
if (item) {
|
||||
if (aux_return)
|
||||
*(void **)aux_return = (void *)((char *)item->key + item->key_size);
|
||||
|
||||
update_cache_last(cache, cache_id, item->bo);
|
||||
bo_reference(bo_out, item->bo);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
enum pipe_error
|
||||
brw_upload_cache( struct brw_cache *cache,
|
||||
enum brw_cache_id cache_id,
|
||||
const void *key,
|
||||
GLuint key_size,
|
||||
struct brw_winsys_reloc *relocs,
|
||||
GLuint nr_relocs,
|
||||
const void *data,
|
||||
GLuint data_size,
|
||||
const void *aux,
|
||||
void *aux_return,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item);
|
||||
GLuint hash = hash_key(key, key_size, relocs, nr_relocs);
|
||||
GLuint relocs_size = nr_relocs * sizeof relocs[0];
|
||||
GLuint aux_size = cache->aux_size[cache_id];
|
||||
enum pipe_error ret;
|
||||
void *tmp;
|
||||
int i;
|
||||
|
||||
/* Create the buffer object to contain the data. For now, use a
|
||||
* single buffer type to describe all cached state atoms. Later,
|
||||
* may want to take advantage of hardware distinctions between
|
||||
* these various entities.
|
||||
*/
|
||||
ret = cache->sws->bo_alloc(cache->sws,
|
||||
cache->buffer_type,
|
||||
data_size, 1 << 6,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
/* Set up the memory containing the key, aux_data, and relocs */
|
||||
tmp = MALLOC(key_size + aux_size + relocs_size);
|
||||
|
||||
memcpy(tmp, key, key_size);
|
||||
memcpy((char *)tmp + key_size, aux, cache->aux_size[cache_id]);
|
||||
memcpy((char *)tmp + key_size + aux_size, relocs, relocs_size);
|
||||
for (i = 0; i < nr_relocs; i++) {
|
||||
p_atomic_inc(&relocs[i].bo->reference.count);
|
||||
}
|
||||
|
||||
item->cache_id = cache_id;
|
||||
item->key = tmp;
|
||||
item->hash = hash;
|
||||
item->key_size = key_size;
|
||||
item->relocs = (struct brw_winsys_reloc *)((char *)tmp + key_size + aux_size);
|
||||
item->nr_relocs = nr_relocs;
|
||||
bo_reference( &item->bo, *bo_out );
|
||||
item->data_size = data_size;
|
||||
|
||||
if (cache->n_items > cache->size * 1.5)
|
||||
rehash(cache);
|
||||
|
||||
hash %= cache->size;
|
||||
item->next = cache->items[hash];
|
||||
cache->items[hash] = item;
|
||||
cache->n_items++;
|
||||
|
||||
if (aux_return) {
|
||||
assert(cache->aux_size[cache_id]);
|
||||
*(void **)aux_return = (void *)((char *)item->key + item->key_size);
|
||||
}
|
||||
|
||||
if (BRW_DEBUG & DEBUG_STATE)
|
||||
debug_printf("upload %s: %d bytes to cache id %d\n",
|
||||
cache->name[cache_id],
|
||||
data_size, cache_id);
|
||||
|
||||
/* Copy data to the buffer */
|
||||
ret = cache->sws->bo_subdata(item->bo,
|
||||
cache_id,
|
||||
0, data_size, data,
|
||||
relocs, nr_relocs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
update_cache_last(cache, cache_id, item->bo);
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This doesn't really work with aux data. Use search/upload instead
|
||||
*/
|
||||
enum pipe_error
|
||||
brw_cache_data_sz(struct brw_cache *cache,
|
||||
enum brw_cache_id cache_id,
|
||||
const void *data,
|
||||
GLuint data_size,
|
||||
struct brw_winsys_reloc *relocs,
|
||||
GLuint nr_relocs,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
struct brw_cache_item *item;
|
||||
GLuint hash = hash_key(data, data_size, relocs, nr_relocs);
|
||||
|
||||
item = search_cache(cache, cache_id, hash, data, data_size,
|
||||
relocs, nr_relocs);
|
||||
if (item) {
|
||||
update_cache_last(cache, cache_id, item->bo);
|
||||
|
||||
bo_reference(bo_out, item->bo);
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
return brw_upload_cache(cache, cache_id,
|
||||
data, data_size,
|
||||
relocs, nr_relocs,
|
||||
data, data_size,
|
||||
NULL, NULL,
|
||||
bo_out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper around brw_cache_data_sz using the cache_id's canonical key size.
|
||||
*
|
||||
* If nr_relocs is nonzero, brw_search_cache()/brw_upload_cache() would be
|
||||
* better to use, as the potentially changing offsets in the data-used-as-key
|
||||
* will result in excessive cache misses.
|
||||
*
|
||||
* XXX: above is no longer true -- can we remove some code?
|
||||
*/
|
||||
enum pipe_error
|
||||
brw_cache_data(struct brw_cache *cache,
|
||||
enum brw_cache_id cache_id,
|
||||
const void *data,
|
||||
struct brw_winsys_reloc *relocs,
|
||||
GLuint nr_relocs,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
return brw_cache_data_sz(cache, cache_id, data, cache->key_size[cache_id],
|
||||
relocs, nr_relocs, bo_out);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brw_init_cache_id(struct brw_cache *cache,
|
||||
const char *name,
|
||||
enum brw_cache_id id,
|
||||
GLuint key_size,
|
||||
GLuint aux_size)
|
||||
{
|
||||
cache->name[id] = strdup(name);
|
||||
cache->key_size[id] = key_size;
|
||||
cache->aux_size[id] = aux_size;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brw_init_general_state_cache(struct brw_context *brw)
|
||||
{
|
||||
struct brw_cache *cache = &brw->cache;
|
||||
|
||||
cache->brw = brw;
|
||||
cache->sws = brw->sws;
|
||||
|
||||
cache->buffer_type = BRW_BUFFER_TYPE_GENERAL_STATE;
|
||||
|
||||
cache->size = 7;
|
||||
cache->n_items = 0;
|
||||
cache->items = (struct brw_cache_item **)
|
||||
CALLOC(cache->size, sizeof(struct brw_cache_item));
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"CC_VP",
|
||||
BRW_CC_VP,
|
||||
sizeof(struct brw_cc_viewport),
|
||||
0);
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"CC_UNIT",
|
||||
BRW_CC_UNIT,
|
||||
sizeof(struct brw_cc_unit_state),
|
||||
0);
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"WM_PROG",
|
||||
BRW_WM_PROG,
|
||||
sizeof(struct brw_wm_prog_key),
|
||||
sizeof(struct brw_wm_prog_data));
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"SAMPLER_DEFAULT_COLOR",
|
||||
BRW_SAMPLER_DEFAULT_COLOR,
|
||||
sizeof(struct brw_sampler_default_color),
|
||||
0);
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"SAMPLER",
|
||||
BRW_SAMPLER,
|
||||
0, /* variable key/data size */
|
||||
0);
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"WM_UNIT",
|
||||
BRW_WM_UNIT,
|
||||
sizeof(struct brw_wm_unit_state),
|
||||
0);
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"SF_PROG",
|
||||
BRW_SF_PROG,
|
||||
sizeof(struct brw_sf_prog_key),
|
||||
sizeof(struct brw_sf_prog_data));
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"SF_VP",
|
||||
BRW_SF_VP,
|
||||
sizeof(struct brw_sf_viewport),
|
||||
0);
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"SF_UNIT",
|
||||
BRW_SF_UNIT,
|
||||
sizeof(struct brw_sf_unit_state),
|
||||
0);
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"VS_UNIT",
|
||||
BRW_VS_UNIT,
|
||||
sizeof(struct brw_vs_unit_state),
|
||||
0);
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"VS_PROG",
|
||||
BRW_VS_PROG,
|
||||
sizeof(struct brw_vs_prog_key),
|
||||
sizeof(struct brw_vs_prog_data));
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"CLIP_UNIT",
|
||||
BRW_CLIP_UNIT,
|
||||
sizeof(struct brw_clip_unit_state),
|
||||
0);
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"CLIP_PROG",
|
||||
BRW_CLIP_PROG,
|
||||
sizeof(struct brw_clip_prog_key),
|
||||
sizeof(struct brw_clip_prog_data));
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"GS_UNIT",
|
||||
BRW_GS_UNIT,
|
||||
sizeof(struct brw_gs_unit_state),
|
||||
0);
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"GS_PROG",
|
||||
BRW_GS_PROG,
|
||||
sizeof(struct brw_gs_prog_key),
|
||||
sizeof(struct brw_gs_prog_data));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brw_init_surface_state_cache(struct brw_context *brw)
|
||||
{
|
||||
struct brw_cache *cache = &brw->surface_cache;
|
||||
|
||||
cache->brw = brw;
|
||||
cache->sws = brw->sws;
|
||||
|
||||
cache->buffer_type = BRW_BUFFER_TYPE_SURFACE_STATE;
|
||||
|
||||
cache->size = 7;
|
||||
cache->n_items = 0;
|
||||
cache->items = (struct brw_cache_item **)
|
||||
CALLOC(cache->size, sizeof(struct brw_cache_item));
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"SS_SURFACE",
|
||||
BRW_SS_SURFACE,
|
||||
sizeof(struct brw_surface_state),
|
||||
0);
|
||||
|
||||
brw_init_cache_id(cache,
|
||||
"SS_SURF_BIND",
|
||||
BRW_SS_SURF_BIND,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
brw_init_caches(struct brw_context *brw)
|
||||
{
|
||||
brw_init_general_state_cache(brw);
|
||||
brw_init_surface_state_cache(brw);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brw_clear_cache(struct brw_context *brw, struct brw_cache *cache)
|
||||
{
|
||||
struct brw_cache_item *c, *next;
|
||||
GLuint i;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_STATE)
|
||||
debug_printf("%s\n", __FUNCTION__);
|
||||
|
||||
for (i = 0; i < cache->size; i++) {
|
||||
for (c = cache->items[i]; c; c = next) {
|
||||
int j;
|
||||
|
||||
next = c->next;
|
||||
|
||||
for (j = 0; j < c->nr_relocs; j++)
|
||||
bo_reference(&c->relocs[j].bo, NULL);
|
||||
|
||||
bo_reference(&c->bo, NULL);
|
||||
FREE((void *)c->key);
|
||||
FREE(c);
|
||||
}
|
||||
cache->items[i] = NULL;
|
||||
}
|
||||
|
||||
cache->n_items = 0;
|
||||
|
||||
if (brw->curbe.last_buf) {
|
||||
FREE(brw->curbe.last_buf);
|
||||
brw->curbe.last_buf = NULL;
|
||||
}
|
||||
|
||||
brw->state.dirty.mesa |= ~0;
|
||||
brw->state.dirty.brw |= ~0;
|
||||
brw->state.dirty.cache |= ~0;
|
||||
}
|
||||
|
||||
/* Clear all entries from the cache that point to the given bo.
|
||||
*
|
||||
* This lets us release memory for reuse earlier for known-dead buffers,
|
||||
* at the cost of walking the entire hash table.
|
||||
*/
|
||||
void
|
||||
brw_state_cache_bo_delete(struct brw_cache *cache, struct brw_winsys_buffer *bo)
|
||||
{
|
||||
struct brw_cache_item **prev;
|
||||
GLuint i;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_STATE)
|
||||
debug_printf("%s\n", __FUNCTION__);
|
||||
|
||||
for (i = 0; i < cache->size; i++) {
|
||||
for (prev = &cache->items[i]; *prev;) {
|
||||
struct brw_cache_item *c = *prev;
|
||||
|
||||
if (cache->sws->bo_references(c->bo, bo)) {
|
||||
int j;
|
||||
|
||||
*prev = c->next;
|
||||
|
||||
for (j = 0; j < c->nr_relocs; j++)
|
||||
bo_reference(&c->relocs[j].bo, NULL);
|
||||
|
||||
bo_reference(&c->bo, NULL);
|
||||
|
||||
FREE((void *)c->key);
|
||||
FREE(c);
|
||||
cache->n_items--;
|
||||
} else {
|
||||
prev = &c->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
brw_state_cache_check_size(struct brw_context *brw)
|
||||
{
|
||||
if (BRW_DEBUG & DEBUG_STATE)
|
||||
debug_printf("%s (n_items=%d)\n", __FUNCTION__, brw->cache.n_items);
|
||||
|
||||
/* un-tuned guess. We've got around 20 state objects for a total of around
|
||||
* 32k, so 1000 of them is around 1.5MB.
|
||||
*/
|
||||
if (brw->cache.n_items > 1000)
|
||||
brw_clear_cache(brw, &brw->cache);
|
||||
|
||||
if (brw->surface_cache.n_items > 1000)
|
||||
brw_clear_cache(brw, &brw->surface_cache);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brw_destroy_cache(struct brw_context *brw, struct brw_cache *cache)
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_STATE)
|
||||
debug_printf("%s\n", __FUNCTION__);
|
||||
|
||||
brw_clear_cache(brw, cache);
|
||||
for (i = 0; i < BRW_MAX_CACHE; i++) {
|
||||
bo_reference(&cache->last_bo[i], NULL);
|
||||
FREE(cache->name[i]);
|
||||
}
|
||||
FREE(cache->items);
|
||||
cache->items = NULL;
|
||||
cache->size = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
brw_destroy_caches(struct brw_context *brw)
|
||||
{
|
||||
brw_destroy_cache(brw, &brw->cache);
|
||||
brw_destroy_cache(brw, &brw->surface_cache);
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
|
||||
|
||||
struct dirty_bit_map {
|
||||
uint32_t bit;
|
||||
char *name;
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
#define DEFINE_BIT(name) {name, #name, 0}
|
||||
|
||||
static struct dirty_bit_map mesa_bits[] = {
|
||||
DEFINE_BIT(PIPE_NEW_DEPTH_STENCIL_ALPHA),
|
||||
DEFINE_BIT(PIPE_NEW_RAST),
|
||||
DEFINE_BIT(PIPE_NEW_BLEND),
|
||||
DEFINE_BIT(PIPE_NEW_VIEWPORT),
|
||||
DEFINE_BIT(PIPE_NEW_SAMPLERS),
|
||||
DEFINE_BIT(PIPE_NEW_VERTEX_BUFFER),
|
||||
DEFINE_BIT(PIPE_NEW_VERTEX_ELEMENT),
|
||||
DEFINE_BIT(PIPE_NEW_FRAGMENT_SHADER),
|
||||
DEFINE_BIT(PIPE_NEW_VERTEX_SHADER),
|
||||
DEFINE_BIT(PIPE_NEW_FRAGMENT_CONSTANTS),
|
||||
DEFINE_BIT(PIPE_NEW_VERTEX_CONSTANTS),
|
||||
DEFINE_BIT(PIPE_NEW_CLIP),
|
||||
DEFINE_BIT(PIPE_NEW_INDEX_BUFFER),
|
||||
DEFINE_BIT(PIPE_NEW_INDEX_RANGE),
|
||||
DEFINE_BIT(PIPE_NEW_BLEND_COLOR),
|
||||
DEFINE_BIT(PIPE_NEW_POLYGON_STIPPLE),
|
||||
DEFINE_BIT(PIPE_NEW_FRAMEBUFFER_DIMENSIONS),
|
||||
DEFINE_BIT(PIPE_NEW_DEPTH_BUFFER),
|
||||
DEFINE_BIT(PIPE_NEW_COLOR_BUFFERS),
|
||||
DEFINE_BIT(PIPE_NEW_QUERY),
|
||||
DEFINE_BIT(PIPE_NEW_SCISSOR),
|
||||
DEFINE_BIT(PIPE_NEW_BOUND_TEXTURES),
|
||||
DEFINE_BIT(PIPE_NEW_NR_CBUFS),
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
static struct dirty_bit_map brw_bits[] = {
|
||||
DEFINE_BIT(BRW_NEW_URB_FENCE),
|
||||
DEFINE_BIT(BRW_NEW_FRAGMENT_PROGRAM),
|
||||
DEFINE_BIT(BRW_NEW_VERTEX_PROGRAM),
|
||||
DEFINE_BIT(BRW_NEW_INPUT_DIMENSIONS),
|
||||
DEFINE_BIT(BRW_NEW_CURBE_OFFSETS),
|
||||
DEFINE_BIT(BRW_NEW_REDUCED_PRIMITIVE),
|
||||
DEFINE_BIT(BRW_NEW_PRIMITIVE),
|
||||
DEFINE_BIT(BRW_NEW_CONTEXT),
|
||||
DEFINE_BIT(BRW_NEW_WM_INPUT_DIMENSIONS),
|
||||
DEFINE_BIT(BRW_NEW_PSP),
|
||||
DEFINE_BIT(BRW_NEW_WM_SURFACES),
|
||||
DEFINE_BIT(BRW_NEW_xxx),
|
||||
DEFINE_BIT(BRW_NEW_INDICES),
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
static struct dirty_bit_map cache_bits[] = {
|
||||
DEFINE_BIT(CACHE_NEW_CC_VP),
|
||||
DEFINE_BIT(CACHE_NEW_CC_UNIT),
|
||||
DEFINE_BIT(CACHE_NEW_WM_PROG),
|
||||
DEFINE_BIT(CACHE_NEW_SAMPLER_DEFAULT_COLOR),
|
||||
DEFINE_BIT(CACHE_NEW_SAMPLER),
|
||||
DEFINE_BIT(CACHE_NEW_WM_UNIT),
|
||||
DEFINE_BIT(CACHE_NEW_SF_PROG),
|
||||
DEFINE_BIT(CACHE_NEW_SF_VP),
|
||||
DEFINE_BIT(CACHE_NEW_SF_UNIT),
|
||||
DEFINE_BIT(CACHE_NEW_VS_UNIT),
|
||||
DEFINE_BIT(CACHE_NEW_VS_PROG),
|
||||
DEFINE_BIT(CACHE_NEW_GS_UNIT),
|
||||
DEFINE_BIT(CACHE_NEW_GS_PROG),
|
||||
DEFINE_BIT(CACHE_NEW_CLIP_VP),
|
||||
DEFINE_BIT(CACHE_NEW_CLIP_UNIT),
|
||||
DEFINE_BIT(CACHE_NEW_CLIP_PROG),
|
||||
DEFINE_BIT(CACHE_NEW_SURFACE),
|
||||
DEFINE_BIT(CACHE_NEW_SURF_BIND),
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
brw_update_dirty_count(struct dirty_bit_map *bit_map, int32_t bits)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (bit_map[i].bit == 0)
|
||||
return;
|
||||
|
||||
if (bit_map[i].bit & bits)
|
||||
bit_map[i].count++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
brw_print_dirty_count(struct dirty_bit_map *bit_map, int32_t bits)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (bit_map[i].bit == 0)
|
||||
return;
|
||||
|
||||
debug_printf("0x%08x: %12d (%s)\n",
|
||||
bit_map[i].bit, bit_map[i].count, bit_map[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
brw_update_dirty_counts( unsigned mesa,
|
||||
unsigned brw,
|
||||
unsigned cache )
|
||||
{
|
||||
static int dirty_count = 0;
|
||||
|
||||
brw_update_dirty_count(mesa_bits, mesa);
|
||||
brw_update_dirty_count(brw_bits, brw);
|
||||
brw_update_dirty_count(cache_bits, cache);
|
||||
if (dirty_count++ % 1000 == 0) {
|
||||
brw_print_dirty_count(mesa_bits, mesa);
|
||||
brw_print_dirty_count(brw_bits, brw);
|
||||
brw_print_dirty_count(cache_bits, cache);
|
||||
debug_printf("\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_debug.h"
|
||||
|
||||
const struct brw_tracked_state *atoms[] =
|
||||
{
|
||||
/* &brw_wm_input_sizes, */
|
||||
&brw_vs_prog,
|
||||
&brw_gs_prog,
|
||||
&brw_clip_prog,
|
||||
&brw_sf_prog,
|
||||
&brw_wm_prog,
|
||||
|
||||
/* Once all the programs are done, we know how large urb entry
|
||||
* sizes need to be and can decide if we need to change the urb
|
||||
* layout.
|
||||
*/
|
||||
&brw_curbe_offsets,
|
||||
&brw_recalculate_urb_fence,
|
||||
|
||||
&brw_cc_vp,
|
||||
&brw_cc_unit,
|
||||
|
||||
&brw_vs_surfaces, /* must do before unit */
|
||||
/*&brw_wm_constant_surface,*/ /* must do before wm surfaces/bind bo */
|
||||
&brw_wm_surfaces, /* must do before samplers and unit */
|
||||
&brw_wm_samplers,
|
||||
|
||||
&brw_wm_unit,
|
||||
&brw_sf_vp,
|
||||
&brw_sf_unit,
|
||||
&brw_vs_unit, /* always required, enabled or not */
|
||||
&brw_clip_unit,
|
||||
&brw_gs_unit,
|
||||
|
||||
/* Command packets:
|
||||
*/
|
||||
&brw_invarient_state,
|
||||
&brw_state_base_address,
|
||||
|
||||
&brw_binding_table_pointers,
|
||||
&brw_blend_constant_color,
|
||||
|
||||
&brw_depthbuffer,
|
||||
&brw_polygon_stipple,
|
||||
&brw_line_stipple,
|
||||
|
||||
&brw_psp_urb_cbs,
|
||||
|
||||
&brw_drawing_rect,
|
||||
&brw_indices,
|
||||
&brw_index_buffer,
|
||||
&brw_vertices,
|
||||
|
||||
&brw_curbe_buffer
|
||||
};
|
||||
|
||||
|
||||
void brw_init_state( struct brw_context *brw )
|
||||
{
|
||||
brw_init_caches(brw);
|
||||
}
|
||||
|
||||
|
||||
void brw_destroy_state( struct brw_context *brw )
|
||||
{
|
||||
brw_destroy_caches(brw);
|
||||
brw_destroy_batch_cache(brw);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*/
|
||||
|
||||
static GLboolean check_state( const struct brw_state_flags *a,
|
||||
const struct brw_state_flags *b )
|
||||
{
|
||||
return ((a->mesa & b->mesa) ||
|
||||
(a->brw & b->brw) ||
|
||||
(a->cache & b->cache));
|
||||
}
|
||||
|
||||
static void accumulate_state( struct brw_state_flags *a,
|
||||
const struct brw_state_flags *b )
|
||||
{
|
||||
a->mesa |= b->mesa;
|
||||
a->brw |= b->brw;
|
||||
a->cache |= b->cache;
|
||||
}
|
||||
|
||||
|
||||
static void xor_states( struct brw_state_flags *result,
|
||||
const struct brw_state_flags *a,
|
||||
const struct brw_state_flags *b )
|
||||
{
|
||||
result->mesa = a->mesa ^ b->mesa;
|
||||
result->brw = a->brw ^ b->brw;
|
||||
result->cache = a->cache ^ b->cache;
|
||||
}
|
||||
|
||||
static void
|
||||
brw_clear_validated_bos(struct brw_context *brw)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Clear the last round of validated bos */
|
||||
for (i = 0; i < brw->state.validated_bo_count; i++) {
|
||||
bo_reference(&brw->state.validated_bos[i], NULL);
|
||||
}
|
||||
brw->state.validated_bo_count = 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Emit all state:
|
||||
*/
|
||||
enum pipe_error brw_validate_state( struct brw_context *brw )
|
||||
{
|
||||
struct brw_state_flags *state = &brw->state.dirty;
|
||||
GLuint i;
|
||||
int ret;
|
||||
|
||||
brw_clear_validated_bos(brw);
|
||||
brw_add_validated_bo(brw, brw->batch->buf);
|
||||
|
||||
if (brw->flags.always_emit_state) {
|
||||
state->mesa |= ~0;
|
||||
state->brw |= ~0;
|
||||
state->cache |= ~0;
|
||||
}
|
||||
|
||||
if (state->mesa == 0 &&
|
||||
state->cache == 0 &&
|
||||
state->brw == 0)
|
||||
return 0;
|
||||
|
||||
if (brw->state.dirty.brw & BRW_NEW_CONTEXT)
|
||||
brw_clear_batch_cache(brw);
|
||||
|
||||
/* do prepare stage for all atoms */
|
||||
for (i = 0; i < Elements(atoms); i++) {
|
||||
const struct brw_tracked_state *atom = atoms[i];
|
||||
|
||||
if (check_state(state, &atom->dirty)) {
|
||||
if (atom->prepare) {
|
||||
ret = atom->prepare(brw);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure that the textures which are referenced by the current
|
||||
* brw fragment program are actually present/valid.
|
||||
* If this fails, we can experience GPU lock-ups.
|
||||
*/
|
||||
{
|
||||
const struct brw_fragment_shader *fp = brw->curr.fragment_shader;
|
||||
if (fp) {
|
||||
assert(fp->info.file_max[TGSI_FILE_SAMPLER] < (int)brw->curr.num_samplers);
|
||||
/*assert(fp->info.texture_max <= brw->curr.num_textures);*/
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
enum pipe_error brw_upload_state(struct brw_context *brw)
|
||||
{
|
||||
struct brw_state_flags *state = &brw->state.dirty;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
brw_clear_validated_bos(brw);
|
||||
|
||||
if (BRW_DEBUG) {
|
||||
/* Debug version which enforces various sanity checks on the
|
||||
* state flags which are generated and checked to help ensure
|
||||
* state atoms are ordered correctly in the list.
|
||||
*/
|
||||
struct brw_state_flags examined, prev;
|
||||
memset(&examined, 0, sizeof(examined));
|
||||
prev = *state;
|
||||
|
||||
for (i = 0; i < Elements(atoms); i++) {
|
||||
const struct brw_tracked_state *atom = atoms[i];
|
||||
struct brw_state_flags generated;
|
||||
|
||||
assert(atom->dirty.mesa ||
|
||||
atom->dirty.brw ||
|
||||
atom->dirty.cache);
|
||||
|
||||
if (check_state(state, &atom->dirty)) {
|
||||
if (atom->emit) {
|
||||
ret = atom->emit( brw );
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
accumulate_state(&examined, &atom->dirty);
|
||||
|
||||
/* generated = (prev ^ state)
|
||||
* if (examined & generated)
|
||||
* fail;
|
||||
*/
|
||||
xor_states(&generated, &prev, state);
|
||||
assert(!check_state(&examined, &generated));
|
||||
prev = *state;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < Elements(atoms); i++) {
|
||||
const struct brw_tracked_state *atom = atoms[i];
|
||||
|
||||
if (check_state(state, &atom->dirty)) {
|
||||
if (atom->emit) {
|
||||
ret = atom->emit( brw );
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BRW_DEBUG & DEBUG_STATE) {
|
||||
brw_update_dirty_counts( state->mesa,
|
||||
state->brw,
|
||||
state->cache );
|
||||
}
|
||||
|
||||
/* Clear dirty flags:
|
||||
*/
|
||||
memset(state, 0, sizeof(*state));
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,276 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009 VMware, Inc.
|
||||
* 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 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
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Dump i965 data structures.
|
||||
*
|
||||
* Generated automatically from brw_structs.h by brw_structs_dump.py.
|
||||
*/
|
||||
|
||||
#ifndef BRW_STRUCTS_DUMP_H
|
||||
#define BRW_STRUCTS_DUMP_H
|
||||
|
||||
struct brw_3d_control;
|
||||
struct brw_3d_primitive;
|
||||
struct brw_aa_line_parameters;
|
||||
struct brw_binding_table_pointers;
|
||||
struct brw_blend_constant_color;
|
||||
struct brw_cc0;
|
||||
struct brw_cc1;
|
||||
struct brw_cc2;
|
||||
struct brw_cc3;
|
||||
struct brw_cc4;
|
||||
struct brw_cc5;
|
||||
struct brw_cc6;
|
||||
struct brw_cc7;
|
||||
struct brw_cc_unit_state;
|
||||
struct brw_cc_viewport;
|
||||
struct brw_clip_unit_state;
|
||||
struct brw_clipper_viewport;
|
||||
struct brw_constant_buffer;
|
||||
struct brw_cs_urb_state;
|
||||
struct brw_depthbuffer;
|
||||
struct brw_depthbuffer_g4x;
|
||||
struct brw_drawrect;
|
||||
struct brw_global_depth_offset_clamp;
|
||||
struct brw_gs_unit_state;
|
||||
struct brw_indexbuffer;
|
||||
struct brw_line_stipple;
|
||||
struct brw_mi_flush;
|
||||
struct brw_pipe_control;
|
||||
struct brw_pipeline_select;
|
||||
struct brw_pipelined_state_pointers;
|
||||
struct brw_polygon_stipple;
|
||||
struct brw_polygon_stipple_offset;
|
||||
struct brw_sampler_default_color;
|
||||
struct brw_sampler_state;
|
||||
struct brw_sf_unit_state;
|
||||
struct brw_sf_viewport;
|
||||
struct brw_ss0;
|
||||
struct brw_ss1;
|
||||
struct brw_ss2;
|
||||
struct brw_ss3;
|
||||
struct brw_state_base_address;
|
||||
struct brw_state_prefetch;
|
||||
struct brw_surf_ss0;
|
||||
struct brw_surf_ss1;
|
||||
struct brw_surf_ss2;
|
||||
struct brw_surf_ss3;
|
||||
struct brw_surf_ss4;
|
||||
struct brw_surf_ss5;
|
||||
struct brw_surface_state;
|
||||
struct brw_system_instruction_pointer;
|
||||
struct brw_urb_fence;
|
||||
struct brw_urb_immediate;
|
||||
struct brw_vb_array_state;
|
||||
struct brw_vertex_buffer_state;
|
||||
struct brw_vertex_element_packet;
|
||||
struct brw_vertex_element_state;
|
||||
struct brw_vf_statistics;
|
||||
struct brw_vs_unit_state;
|
||||
struct brw_wm_unit_state;
|
||||
|
||||
void
|
||||
brw_dump_3d_control(const struct brw_3d_control *ptr);
|
||||
|
||||
void
|
||||
brw_dump_3d_primitive(const struct brw_3d_primitive *ptr);
|
||||
|
||||
void
|
||||
brw_dump_aa_line_parameters(const struct brw_aa_line_parameters *ptr);
|
||||
|
||||
void
|
||||
brw_dump_binding_table_pointers(const struct brw_binding_table_pointers *ptr);
|
||||
|
||||
void
|
||||
brw_dump_blend_constant_color(const struct brw_blend_constant_color *ptr);
|
||||
|
||||
void
|
||||
brw_dump_cc0(const struct brw_cc0 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_cc1(const struct brw_cc1 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_cc2(const struct brw_cc2 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_cc3(const struct brw_cc3 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_cc4(const struct brw_cc4 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_cc5(const struct brw_cc5 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_cc6(const struct brw_cc6 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_cc7(const struct brw_cc7 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_cc_unit_state(const struct brw_cc_unit_state *ptr);
|
||||
|
||||
void
|
||||
brw_dump_cc_viewport(const struct brw_cc_viewport *ptr);
|
||||
|
||||
void
|
||||
brw_dump_clip_unit_state(const struct brw_clip_unit_state *ptr);
|
||||
|
||||
void
|
||||
brw_dump_clipper_viewport(const struct brw_clipper_viewport *ptr);
|
||||
|
||||
void
|
||||
brw_dump_constant_buffer(const struct brw_constant_buffer *ptr);
|
||||
|
||||
void
|
||||
brw_dump_cs_urb_state(const struct brw_cs_urb_state *ptr);
|
||||
|
||||
void
|
||||
brw_dump_depthbuffer(const struct brw_depthbuffer *ptr);
|
||||
|
||||
void
|
||||
brw_dump_depthbuffer_g4x(const struct brw_depthbuffer_g4x *ptr);
|
||||
|
||||
void
|
||||
brw_dump_drawrect(const struct brw_drawrect *ptr);
|
||||
|
||||
void
|
||||
brw_dump_global_depth_offset_clamp(const struct brw_global_depth_offset_clamp *ptr);
|
||||
|
||||
void
|
||||
brw_dump_gs_unit_state(const struct brw_gs_unit_state *ptr);
|
||||
|
||||
void
|
||||
brw_dump_indexbuffer(const struct brw_indexbuffer *ptr);
|
||||
|
||||
void
|
||||
brw_dump_line_stipple(const struct brw_line_stipple *ptr);
|
||||
|
||||
void
|
||||
brw_dump_mi_flush(const struct brw_mi_flush *ptr);
|
||||
|
||||
void
|
||||
brw_dump_pipe_control(const struct brw_pipe_control *ptr);
|
||||
|
||||
void
|
||||
brw_dump_pipeline_select(const struct brw_pipeline_select *ptr);
|
||||
|
||||
void
|
||||
brw_dump_pipelined_state_pointers(const struct brw_pipelined_state_pointers *ptr);
|
||||
|
||||
void
|
||||
brw_dump_polygon_stipple(const struct brw_polygon_stipple *ptr);
|
||||
|
||||
void
|
||||
brw_dump_polygon_stipple_offset(const struct brw_polygon_stipple_offset *ptr);
|
||||
|
||||
void
|
||||
brw_dump_sampler_default_color(const struct brw_sampler_default_color *ptr);
|
||||
|
||||
void
|
||||
brw_dump_sampler_state(const struct brw_sampler_state *ptr);
|
||||
|
||||
void
|
||||
brw_dump_sf_unit_state(const struct brw_sf_unit_state *ptr);
|
||||
|
||||
void
|
||||
brw_dump_sf_viewport(const struct brw_sf_viewport *ptr);
|
||||
|
||||
void
|
||||
brw_dump_ss0(const struct brw_ss0 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_ss1(const struct brw_ss1 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_ss2(const struct brw_ss2 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_ss3(const struct brw_ss3 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_state_base_address(const struct brw_state_base_address *ptr);
|
||||
|
||||
void
|
||||
brw_dump_state_prefetch(const struct brw_state_prefetch *ptr);
|
||||
|
||||
void
|
||||
brw_dump_surf_ss0(const struct brw_surf_ss0 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_surf_ss1(const struct brw_surf_ss1 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_surf_ss2(const struct brw_surf_ss2 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_surf_ss3(const struct brw_surf_ss3 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_surf_ss4(const struct brw_surf_ss4 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_surf_ss5(const struct brw_surf_ss5 *ptr);
|
||||
|
||||
void
|
||||
brw_dump_surface_state(const struct brw_surface_state *ptr);
|
||||
|
||||
void
|
||||
brw_dump_system_instruction_pointer(const struct brw_system_instruction_pointer *ptr);
|
||||
|
||||
void
|
||||
brw_dump_urb_fence(const struct brw_urb_fence *ptr);
|
||||
|
||||
void
|
||||
brw_dump_urb_immediate(const struct brw_urb_immediate *ptr);
|
||||
|
||||
void
|
||||
brw_dump_vb_array_state(const struct brw_vb_array_state *ptr);
|
||||
|
||||
void
|
||||
brw_dump_vertex_buffer_state(const struct brw_vertex_buffer_state *ptr);
|
||||
|
||||
void
|
||||
brw_dump_vertex_element_packet(const struct brw_vertex_element_packet *ptr);
|
||||
|
||||
void
|
||||
brw_dump_vertex_element_state(const struct brw_vertex_element_state *ptr);
|
||||
|
||||
void
|
||||
brw_dump_vf_statistics(const struct brw_vf_statistics *ptr);
|
||||
|
||||
void
|
||||
brw_dump_vs_unit_state(const struct brw_vs_unit_state *ptr);
|
||||
|
||||
void
|
||||
brw_dump_wm_unit_state(const struct brw_wm_unit_state *ptr);
|
||||
|
||||
|
||||
#endif /* BRW_STRUCTS_DUMP_H */
|
||||
Executable
+291
@@ -0,0 +1,291 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Generates dumpers for the i965 state strucutures using pygccxml.
|
||||
|
||||
Run as
|
||||
|
||||
PYTHONPATH=/path/to/pygccxml-1.0.0 python brw_structs_dump.py
|
||||
|
||||
Jose Fonseca <jfonseca@vmware.com>
|
||||
'''
|
||||
|
||||
copyright = '''
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009 VMware, Inc.
|
||||
* 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 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
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
'''
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
|
||||
from pygccxml import parser
|
||||
from pygccxml import declarations
|
||||
|
||||
from pygccxml.declarations import algorithm
|
||||
from pygccxml.declarations import decl_visitor
|
||||
from pygccxml.declarations import type_traits
|
||||
from pygccxml.declarations import type_visitor
|
||||
|
||||
|
||||
enums = True
|
||||
|
||||
|
||||
def vars_filter(variable):
|
||||
name = variable.name
|
||||
return not re.match('^pad\d*', name) and name != 'dword'
|
||||
|
||||
|
||||
class decl_dumper_t(decl_visitor.decl_visitor_t):
|
||||
|
||||
def __init__(self, stream, instance = '', decl = None):
|
||||
decl_visitor.decl_visitor_t.__init__(self)
|
||||
self.stream = stream
|
||||
self._instance = instance
|
||||
self.decl = decl
|
||||
|
||||
def clone(self):
|
||||
return decl_dumper_t(self.stream, self._instance, self.decl)
|
||||
|
||||
def visit_class(self):
|
||||
class_ = self.decl
|
||||
assert self.decl.class_type in ('struct', 'union')
|
||||
|
||||
for variable in class_.variables(recursive = False):
|
||||
if vars_filter(variable):
|
||||
dump_type(self.stream, self._instance + '.' + variable.name, variable.type)
|
||||
|
||||
def visit_enumeration(self):
|
||||
if enums:
|
||||
self.stream.write(' switch(%s) {\n' % ("(*ptr)" + self._instance,))
|
||||
for name, value in self.decl.values:
|
||||
self.stream.write(' case %s:\n' % (name,))
|
||||
self.stream.write(' debug_printf("\\t\\t%s = %s\\n");\n' % (self._instance, name))
|
||||
self.stream.write(' break;\n')
|
||||
self.stream.write(' default:\n')
|
||||
self.stream.write(' debug_printf("\\t\\t%s = %%i\\n", %s);\n' % (self._instance, "(*ptr)" + self._instance))
|
||||
self.stream.write(' break;\n')
|
||||
self.stream.write(' }\n')
|
||||
else:
|
||||
self.stream.write(' debug_printf("\\t\\t%s = %%i\\n", %s);\n' % (self._instance, "(*ptr)" + self._instance))
|
||||
|
||||
|
||||
def dump_decl(stream, instance, decl):
|
||||
dumper = decl_dumper_t(stream, instance, decl)
|
||||
algorithm.apply_visitor(dumper, decl)
|
||||
|
||||
|
||||
class type_dumper_t(type_visitor.type_visitor_t):
|
||||
|
||||
def __init__(self, stream, instance, type_):
|
||||
type_visitor.type_visitor_t.__init__(self)
|
||||
self.stream = stream
|
||||
self.instance = instance
|
||||
self.type = type_
|
||||
|
||||
def clone(self):
|
||||
return type_dumper_t(self.instance, self.type)
|
||||
|
||||
def visit_bool(self):
|
||||
self.print_instance('%i')
|
||||
|
||||
def visit_char(self):
|
||||
#self.print_instance('%i')
|
||||
self.print_instance('0x%x')
|
||||
|
||||
def visit_unsigned_char(self):
|
||||
#self.print_instance('%u')
|
||||
self.print_instance('0x%x')
|
||||
|
||||
def visit_signed_char(self):
|
||||
#self.print_instance('%i')
|
||||
self.print_instance('0x%x')
|
||||
|
||||
def visit_wchar(self):
|
||||
self.print_instance('0x%x')
|
||||
|
||||
def visit_short_int(self):
|
||||
#self.print_instance('%i')
|
||||
self.print_instance('0x%x')
|
||||
|
||||
def visit_short_unsigned_int(self):
|
||||
#self.print_instance('%u')
|
||||
self.print_instance('0x%x')
|
||||
|
||||
def visit_int(self):
|
||||
#self.print_instance('%i')
|
||||
self.print_instance('0x%x')
|
||||
|
||||
def visit_unsigned_int(self):
|
||||
#self.print_instance('%u')
|
||||
self.print_instance('0x%x')
|
||||
|
||||
def visit_long_int(self):
|
||||
#self.print_instance('%li')
|
||||
self.print_instance('0x%lx')
|
||||
|
||||
def visit_long_unsigned_int(self):
|
||||
#self.print_instance('%lu')
|
||||
self.print_instance('%0xlx')
|
||||
|
||||
def visit_long_long_int(self):
|
||||
#self.print_instance('%lli')
|
||||
self.print_instance('%0xllx')
|
||||
|
||||
def visit_long_long_unsigned_int(self):
|
||||
#self.print_instance('%llu')
|
||||
self.print_instance('0x%llx')
|
||||
|
||||
def visit_float(self):
|
||||
self.print_instance('%f')
|
||||
|
||||
def visit_double(self):
|
||||
self.print_instance('%f')
|
||||
|
||||
def visit_array(self):
|
||||
for i in range(type_traits.array_size(self.type)):
|
||||
dump_type(self.stream, self.instance + '[%i]' % i, type_traits.base_type(self.type))
|
||||
|
||||
def visit_pointer(self):
|
||||
self.print_instance('%p')
|
||||
|
||||
def visit_declarated(self):
|
||||
#stream.write('decl = %r\n' % self.type.decl_string)
|
||||
decl = type_traits.remove_declarated(self.type)
|
||||
dump_decl(self.stream, self.instance, decl)
|
||||
|
||||
def print_instance(self, format):
|
||||
self.stream.write(' debug_printf("\\t\\t%s = %s\\n", %s);\n' % (self.instance, format, "(*ptr)" + self.instance))
|
||||
|
||||
|
||||
|
||||
def dump_type(stream, instance, type_):
|
||||
type_ = type_traits.remove_alias(type_)
|
||||
visitor = type_dumper_t(stream, instance, type_)
|
||||
algorithm.apply_visitor(visitor, type_)
|
||||
|
||||
|
||||
def dump_struct_interface(stream, class_, suffix = ';'):
|
||||
name = class_.name
|
||||
assert name.startswith('brw_');
|
||||
name = name[:4] + 'dump_' + name[4:]
|
||||
stream.write('void\n')
|
||||
stream.write('%s(const struct %s *ptr)%s\n' % (name, class_.name, suffix))
|
||||
|
||||
|
||||
def dump_struct_implementation(stream, decls, class_):
|
||||
dump_struct_interface(stream, class_, suffix = '')
|
||||
stream.write('{\n')
|
||||
dump_decl(stream, '', class_)
|
||||
stream.write('}\n')
|
||||
stream.write('\n')
|
||||
|
||||
|
||||
def dump_header(stream):
|
||||
stream.write(copyright.strip() + '\n')
|
||||
stream.write('\n')
|
||||
stream.write('/**\n')
|
||||
stream.write(' * @file\n')
|
||||
stream.write(' * Dump i965 data structures.\n')
|
||||
stream.write(' *\n')
|
||||
stream.write(' * Generated automatically from brw_structs.h by brw_structs_dump.py.\n')
|
||||
stream.write(' */\n')
|
||||
stream.write('\n')
|
||||
|
||||
|
||||
def dump_interfaces(decls, global_ns, names):
|
||||
stream = open('brw_structs_dump.h', 'wt')
|
||||
|
||||
dump_header(stream)
|
||||
|
||||
stream.write('#ifndef BRW_STRUCTS_DUMP_H\n')
|
||||
stream.write('#define BRW_STRUCTS_DUMP_H\n')
|
||||
stream.write('\n')
|
||||
|
||||
for name in names:
|
||||
stream.write('struct %s;\n' % (name,))
|
||||
stream.write('\n')
|
||||
|
||||
for name in names:
|
||||
(class_,) = global_ns.classes(name = name)
|
||||
dump_struct_interface(stream, class_)
|
||||
stream.write('\n')
|
||||
stream.write('\n')
|
||||
|
||||
stream.write('#endif /* BRW_STRUCTS_DUMP_H */\n')
|
||||
|
||||
|
||||
def dump_implementations(decls, global_ns, names):
|
||||
stream = open('brw_structs_dump.c', 'wt')
|
||||
|
||||
dump_header(stream)
|
||||
|
||||
stream.write('#include "util/u_debug.h"\n')
|
||||
stream.write('\n')
|
||||
stream.write('#include "brw_types.h"\n')
|
||||
stream.write('#include "brw_structs.h"\n')
|
||||
stream.write('#include "brw_structs_dump.h"\n')
|
||||
stream.write('\n')
|
||||
|
||||
for name in names:
|
||||
(class_,) = global_ns.classes(name = name)
|
||||
dump_struct_implementation(stream, decls, class_)
|
||||
|
||||
|
||||
def decl_filter(decl):
|
||||
'''Filter the declarations we're interested in'''
|
||||
name = decl.name
|
||||
return name.startswith('brw_') and name not in ('brw_instruction',)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
config = parser.config_t(
|
||||
include_paths = [
|
||||
'../../include',
|
||||
],
|
||||
compiler = 'gcc',
|
||||
)
|
||||
|
||||
headers = [
|
||||
'brw_types.h',
|
||||
'brw_structs.h',
|
||||
]
|
||||
|
||||
decls = parser.parse(headers, config, parser.COMPILATION_MODE.ALL_AT_ONCE)
|
||||
global_ns = declarations.get_global_namespace(decls)
|
||||
|
||||
names = []
|
||||
for class_ in global_ns.classes(decl_filter):
|
||||
names.append(class_.name)
|
||||
names.sort()
|
||||
|
||||
dump_interfaces(decls, global_ns, names)
|
||||
dump_implementations(decls, global_ns, names)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,95 @@
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_pipe_rast.h"
|
||||
|
||||
|
||||
static GLboolean need_swtnl( struct brw_context *brw )
|
||||
{
|
||||
const struct pipe_rasterizer_state *rast = &brw->curr.rast->templ;
|
||||
|
||||
/* If we don't require strict OpenGL conformance, never
|
||||
* use fallbacks. If we're forcing fallbacks, always
|
||||
* use fallfacks.
|
||||
*/
|
||||
if (brw->flags.no_swtnl)
|
||||
return FALSE;
|
||||
|
||||
if (brw->flags.force_swtnl)
|
||||
return TRUE;
|
||||
|
||||
/* Exceeding hw limits on number of VS inputs?
|
||||
*/
|
||||
if (brw->curr.num_vertex_elements == 0 ||
|
||||
brw->curr.num_vertex_elements >= BRW_VEP_MAX) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Position array with zero stride?
|
||||
*
|
||||
* XXX: position isn't always at zero...
|
||||
* XXX: eliminate zero-stride arrays
|
||||
*/
|
||||
{
|
||||
int ve0_vb = brw->curr.vertex_element[0].vertex_buffer_index;
|
||||
|
||||
if (brw->curr.vertex_buffer[ve0_vb].stride == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* XXX: short-circuit
|
||||
*/
|
||||
return FALSE;
|
||||
|
||||
if (brw->reduced_primitive == PIPE_PRIM_TRIANGLES) {
|
||||
if (rast->poly_smooth)
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
if (brw->reduced_primitive == PIPE_PRIM_LINES ||
|
||||
(brw->reduced_primitive == PIPE_PRIM_TRIANGLES &&
|
||||
(rast->fill_cw == PIPE_POLYGON_MODE_LINE ||
|
||||
rast->fill_ccw == PIPE_POLYGON_MODE_LINE)))
|
||||
{
|
||||
/* BRW hardware will do AA lines, but they are non-conformant it
|
||||
* seems. TBD whether we keep this fallback:
|
||||
*/
|
||||
if (rast->line_smooth)
|
||||
return TRUE;
|
||||
|
||||
/* XXX: was a fallback in mesa (gs doesn't get enough
|
||||
* information to know when to reset stipple counter), but there
|
||||
* must be a way around it.
|
||||
*/
|
||||
if (rast->line_stipple_enable &&
|
||||
(brw->reduced_primitive == PIPE_PRIM_TRIANGLES ||
|
||||
brw->primitive == PIPE_PRIM_LINE_LOOP ||
|
||||
brw->primitive == PIPE_PRIM_LINE_STRIP))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
if (brw->reduced_primitive == PIPE_PRIM_POINTS ||
|
||||
(brw->reduced_primitive == PIPE_PRIM_TRIANGLES &&
|
||||
(rast->fill_cw == PIPE_POLYGON_MODE_POINT ||
|
||||
rast->fill_ccw == PIPE_POLYGON_MODE_POINT)))
|
||||
{
|
||||
if (rast->point_smooth)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* BRW hardware doesn't handle CLAMP texturing correctly;
|
||||
* brw_wm_sampler_state:translate_wrap_mode() treats CLAMP
|
||||
* as CLAMP_TO_EDGE instead. If we're using CLAMP, and
|
||||
* we want strict conformance, force the fallback.
|
||||
*
|
||||
* XXX: need a workaround for this.
|
||||
*/
|
||||
|
||||
/* Nothing stopping us from the fast path now */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef BRW_TYPES_H
|
||||
#define BRW_TYPES_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
typedef uint32_t GLuint;
|
||||
typedef uint8_t GLubyte;
|
||||
typedef uint16_t GLushort;
|
||||
typedef int32_t GLint;
|
||||
typedef int8_t GLbyte;
|
||||
typedef int16_t GLshort;
|
||||
typedef float GLfloat;
|
||||
|
||||
/* no GLenum, translate all away */
|
||||
|
||||
typedef uint8_t GLboolean;
|
||||
|
||||
#define GL_FALSE FALSE
|
||||
#define GL_TRUE TRUE
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_debug.h"
|
||||
|
||||
#define VS 0
|
||||
#define GS 1
|
||||
#define CLP 2
|
||||
#define SF 3
|
||||
#define CS 4
|
||||
|
||||
/** @file brw_urb.c
|
||||
*
|
||||
* Manages the division of the URB space between the various fixed-function
|
||||
* units.
|
||||
*
|
||||
* See the Thread Initiation Management section of the GEN4 B-Spec, and
|
||||
* the individual *_STATE structures for restrictions on numbers of
|
||||
* entries and threads.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generally, a unit requires a min_nr_entries based on how many entries
|
||||
* it produces before the downstream unit gets unblocked and can use and
|
||||
* dereference some of its handles.
|
||||
*
|
||||
* The SF unit preallocates a PUE at the start of thread dispatch, and only
|
||||
* uses that one. So it requires one entry per thread.
|
||||
*
|
||||
* For CLIP, the SF unit will hold the previous primitive while the
|
||||
* next is getting assembled, meaning that linestrips require 3 CLIP VUEs
|
||||
* (vertices) to ensure continued processing, trifans require 4, and tristrips
|
||||
* require 5. There can be 1 or 2 threads, and each has the same requirement.
|
||||
*
|
||||
* GS has the same requirement as CLIP, but it never handles tristrips,
|
||||
* so we can lower the minimum to 4 for the POLYGONs (trifans) it produces.
|
||||
* We only run it single-threaded.
|
||||
*
|
||||
* For VS, the number of entries may be 8, 12, 16, or 32 (or 64 on G4X).
|
||||
* Each thread processes 2 preallocated VUEs (vertices) at a time, and they
|
||||
* get streamed down as soon as threads processing earlier vertices get
|
||||
* theirs accepted.
|
||||
*
|
||||
* Each unit will take the number of URB entries we give it (based on the
|
||||
* entry size calculated in brw_vs_emit.c for VUEs, brw_sf_emit.c for PUEs,
|
||||
* and brw_curbe.c for the CURBEs) and decide its maximum number of
|
||||
* threads it can support based on that. in brw_*_state.c.
|
||||
*
|
||||
* XXX: Are the min_entry_size numbers useful?
|
||||
* XXX: Verify min_nr_entries, esp for VS.
|
||||
* XXX: Verify SF min_entry_size.
|
||||
*/
|
||||
static const struct urb_limits {
|
||||
GLuint min_nr_entries;
|
||||
GLuint preferred_nr_entries;
|
||||
GLuint min_entry_size;
|
||||
GLuint max_entry_size;
|
||||
} limits[CS+1] = {
|
||||
{ 16, 32, 1, 5 }, /* vs */
|
||||
{ 4, 8, 1, 5 }, /* gs */
|
||||
{ 5, 10, 1, 5 }, /* clp */
|
||||
{ 1, 8, 1, 12 }, /* sf */
|
||||
{ 1, 4, 1, 32 } /* cs */
|
||||
};
|
||||
|
||||
|
||||
static GLboolean check_urb_layout( struct brw_context *brw )
|
||||
{
|
||||
brw->urb.vs_start = 0;
|
||||
brw->urb.gs_start = brw->urb.nr_vs_entries * brw->urb.vsize;
|
||||
brw->urb.clip_start = brw->urb.gs_start + brw->urb.nr_gs_entries * brw->urb.vsize;
|
||||
brw->urb.sf_start = brw->urb.clip_start + brw->urb.nr_clip_entries * brw->urb.vsize;
|
||||
brw->urb.cs_start = brw->urb.sf_start + brw->urb.nr_sf_entries * brw->urb.sfsize;
|
||||
|
||||
return brw->urb.cs_start + brw->urb.nr_cs_entries * brw->urb.csize <= URB_SIZES(brw);
|
||||
}
|
||||
|
||||
/* Most minimal update, forces re-emit of URB fence packet after GS
|
||||
* unit turned on/off.
|
||||
*/
|
||||
static int recalculate_urb_fence( struct brw_context *brw )
|
||||
{
|
||||
GLuint csize = brw->curbe.total_size;
|
||||
GLuint vsize = brw->vs.prog_data->urb_entry_size;
|
||||
GLuint sfsize = brw->sf.prog_data->urb_entry_size;
|
||||
|
||||
if (csize < limits[CS].min_entry_size)
|
||||
csize = limits[CS].min_entry_size;
|
||||
|
||||
if (vsize < limits[VS].min_entry_size)
|
||||
vsize = limits[VS].min_entry_size;
|
||||
|
||||
if (sfsize < limits[SF].min_entry_size)
|
||||
sfsize = limits[SF].min_entry_size;
|
||||
|
||||
if (brw->urb.vsize < vsize ||
|
||||
brw->urb.sfsize < sfsize ||
|
||||
brw->urb.csize < csize ||
|
||||
(brw->urb.constrained && (brw->urb.vsize > vsize ||
|
||||
brw->urb.sfsize > sfsize ||
|
||||
brw->urb.csize > csize))) {
|
||||
|
||||
|
||||
brw->urb.csize = csize;
|
||||
brw->urb.sfsize = sfsize;
|
||||
brw->urb.vsize = vsize;
|
||||
|
||||
brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries;
|
||||
brw->urb.nr_gs_entries = limits[GS].preferred_nr_entries;
|
||||
brw->urb.nr_clip_entries = limits[CLP].preferred_nr_entries;
|
||||
brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries;
|
||||
brw->urb.nr_cs_entries = limits[CS].preferred_nr_entries;
|
||||
|
||||
brw->urb.constrained = 0;
|
||||
|
||||
if (BRW_IS_IGDNG(brw)) {
|
||||
brw->urb.nr_vs_entries = 128;
|
||||
brw->urb.nr_sf_entries = 48;
|
||||
if (check_urb_layout(brw)) {
|
||||
goto done;
|
||||
} else {
|
||||
brw->urb.constrained = 1;
|
||||
brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries;
|
||||
brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries;
|
||||
}
|
||||
} else if (BRW_IS_G4X(brw)) {
|
||||
brw->urb.nr_vs_entries = 64;
|
||||
if (check_urb_layout(brw)) {
|
||||
goto done;
|
||||
} else {
|
||||
brw->urb.constrained = 1;
|
||||
brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries;
|
||||
}
|
||||
}
|
||||
|
||||
if (BRW_DEBUG & DEBUG_MIN_URB) {
|
||||
brw->urb.nr_vs_entries = limits[VS].min_nr_entries;
|
||||
brw->urb.nr_gs_entries = limits[GS].min_nr_entries;
|
||||
brw->urb.nr_clip_entries = limits[CLP].min_nr_entries;
|
||||
brw->urb.nr_sf_entries = limits[SF].min_nr_entries;
|
||||
brw->urb.nr_cs_entries = limits[CS].min_nr_entries;
|
||||
brw->urb.constrained = 1;
|
||||
}
|
||||
|
||||
if (!check_urb_layout(brw)) {
|
||||
brw->urb.nr_vs_entries = limits[VS].min_nr_entries;
|
||||
brw->urb.nr_gs_entries = limits[GS].min_nr_entries;
|
||||
brw->urb.nr_clip_entries = limits[CLP].min_nr_entries;
|
||||
brw->urb.nr_sf_entries = limits[SF].min_nr_entries;
|
||||
brw->urb.nr_cs_entries = limits[CS].min_nr_entries;
|
||||
|
||||
/* Mark us as operating with constrained nr_entries, so that next
|
||||
* time we recalculate we'll resize the fences in the hope of
|
||||
* escaping constrained mode and getting back to normal performance.
|
||||
*/
|
||||
brw->urb.constrained = 1;
|
||||
|
||||
if (!check_urb_layout(brw)) {
|
||||
/* This is impossible, given the maximal sizes of urb
|
||||
* entries and the values for minimum nr of entries
|
||||
* provided above.
|
||||
*/
|
||||
debug_printf("couldn't calculate URB layout!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (BRW_DEBUG & (DEBUG_URB|DEBUG_FALLBACKS))
|
||||
debug_printf("URB CONSTRAINED\n");
|
||||
}
|
||||
|
||||
done:
|
||||
if (BRW_DEBUG & DEBUG_URB)
|
||||
debug_printf("URB fence: %d ..VS.. %d ..GS.. %d ..CLP.. %d ..SF.. %d ..CS.. %d\n",
|
||||
brw->urb.vs_start,
|
||||
brw->urb.gs_start,
|
||||
brw->urb.clip_start,
|
||||
brw->urb.sf_start,
|
||||
brw->urb.cs_start,
|
||||
URB_SIZES(brw));
|
||||
|
||||
brw->state.dirty.brw |= BRW_NEW_URB_FENCE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const struct brw_tracked_state brw_recalculate_urb_fence = {
|
||||
.dirty = {
|
||||
.mesa = 0,
|
||||
.brw = BRW_NEW_CURBE_OFFSETS,
|
||||
.cache = (CACHE_NEW_VS_PROG |
|
||||
CACHE_NEW_SF_PROG)
|
||||
},
|
||||
.prepare = recalculate_urb_fence
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int brw_upload_urb_fence(struct brw_context *brw)
|
||||
{
|
||||
struct brw_urb_fence uf;
|
||||
memset(&uf, 0, sizeof(uf));
|
||||
|
||||
uf.header.opcode = CMD_URB_FENCE;
|
||||
uf.header.length = sizeof(uf)/4-2;
|
||||
uf.header.vs_realloc = 1;
|
||||
uf.header.gs_realloc = 1;
|
||||
uf.header.clp_realloc = 1;
|
||||
uf.header.sf_realloc = 1;
|
||||
uf.header.vfe_realloc = 1;
|
||||
uf.header.cs_realloc = 1;
|
||||
|
||||
/* The ordering below is correct, not the layout in the
|
||||
* instruction.
|
||||
*
|
||||
* There are 256/384 urb reg pairs in total.
|
||||
*/
|
||||
uf.bits0.vs_fence = brw->urb.gs_start;
|
||||
uf.bits0.gs_fence = brw->urb.clip_start;
|
||||
uf.bits0.clp_fence = brw->urb.sf_start;
|
||||
uf.bits1.sf_fence = brw->urb.cs_start;
|
||||
uf.bits1.cs_fence = URB_SIZES(brw);
|
||||
|
||||
BRW_BATCH_STRUCT(brw, &uf);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "brw_util.h"
|
||||
#include "brw_defines.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BRW_UTIL_H
|
||||
#define BRW_UTIL_H
|
||||
|
||||
#include "brw_types.h"
|
||||
|
||||
extern GLuint brw_count_bits( GLuint val );
|
||||
extern GLuint brw_translate_blend_factor( unsigned factor );
|
||||
extern GLuint brw_translate_blend_equation( unsigned mode );
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "tgsi/tgsi_dump.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_vs.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_pipe_rast.h"
|
||||
|
||||
|
||||
|
||||
static enum pipe_error do_vs_prog( struct brw_context *brw,
|
||||
struct brw_vertex_shader *vp,
|
||||
struct brw_vs_prog_key *key,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
enum pipe_error ret;
|
||||
GLuint program_size;
|
||||
const GLuint *program;
|
||||
struct brw_vs_compile c;
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
memcpy(&c.key, key, sizeof(*key));
|
||||
|
||||
brw_init_compile(brw, &c.func);
|
||||
c.vp = vp;
|
||||
|
||||
c.prog_data.nr_outputs = vp->info.num_outputs;
|
||||
c.prog_data.nr_inputs = vp->info.num_inputs;
|
||||
|
||||
/* XXX: we want edgeflag handling to be integrated to the vertex
|
||||
* shader, but are currently faking the edgeflag output:
|
||||
*/
|
||||
if (c.key.copy_edgeflag) {
|
||||
c.prog_data.output_edgeflag = c.prog_data.nr_outputs;
|
||||
c.prog_data.nr_outputs++;
|
||||
}
|
||||
else {
|
||||
c.prog_data.output_edgeflag = ~0;
|
||||
}
|
||||
|
||||
|
||||
if (1)
|
||||
tgsi_dump(c.vp->tokens, 0);
|
||||
|
||||
/* Emit GEN4 code.
|
||||
*/
|
||||
brw_vs_emit(&c);
|
||||
|
||||
/* get the program
|
||||
*/
|
||||
ret = brw_get_program(&c.func, &program, &program_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = brw_upload_cache( &brw->cache, BRW_VS_PROG,
|
||||
&c.key, brw_vs_prog_key_size(&c.key),
|
||||
NULL, 0,
|
||||
program, program_size,
|
||||
&c.prog_data,
|
||||
&brw->vs.prog_data,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
static enum pipe_error brw_upload_vs_prog(struct brw_context *brw)
|
||||
{
|
||||
struct brw_vs_prog_key key;
|
||||
struct brw_vertex_shader *vp = brw->curr.vertex_shader;
|
||||
struct brw_fs_signature *sig = &brw->curr.fragment_shader->signature;
|
||||
enum pipe_error ret;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
|
||||
key.program_string_id = vp->id;
|
||||
key.nr_userclip = brw->curr.ucp.nr;
|
||||
key.copy_edgeflag = (brw->curr.rast->templ.fill_ccw != PIPE_POLYGON_MODE_FILL ||
|
||||
brw->curr.rast->templ.fill_cw != PIPE_POLYGON_MODE_FILL);
|
||||
|
||||
memcpy(&key.fs_signature, sig, brw_fs_signature_size(sig));
|
||||
|
||||
|
||||
/* Make an early check for the key.
|
||||
*/
|
||||
if (brw_search_cache(&brw->cache, BRW_VS_PROG,
|
||||
&key, brw_vs_prog_key_size(&key),
|
||||
NULL, 0,
|
||||
&brw->vs.prog_data,
|
||||
&brw->vs.prog_bo))
|
||||
return PIPE_OK;
|
||||
|
||||
ret = do_vs_prog(brw, vp, &key, &brw->vs.prog_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* See brw_vs.c:
|
||||
*/
|
||||
const struct brw_tracked_state brw_vs_prog = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_CLIP |
|
||||
PIPE_NEW_RAST |
|
||||
PIPE_NEW_FRAGMENT_SIGNATURE),
|
||||
.brw = BRW_NEW_VERTEX_PROGRAM,
|
||||
.cache = 0
|
||||
},
|
||||
.prepare = brw_upload_vs_prog
|
||||
};
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BRW_VS_H
|
||||
#define BRW_VS_H
|
||||
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_eu.h"
|
||||
|
||||
|
||||
struct brw_vs_prog_key {
|
||||
GLuint program_string_id;
|
||||
GLuint nr_userclip:4;
|
||||
GLuint copy_edgeflag:1;
|
||||
GLuint pad:26;
|
||||
struct brw_fs_signature fs_signature;
|
||||
};
|
||||
|
||||
#define brw_vs_prog_key_size(s) (offsetof(struct brw_vs_prog_key, fs_signature) + \
|
||||
brw_fs_signature_size(&(s)->fs_signature))
|
||||
|
||||
|
||||
#define MAX_IF_DEPTH 32
|
||||
#define MAX_LOOP_DEPTH 32
|
||||
|
||||
struct brw_vs_compile {
|
||||
struct brw_compile func;
|
||||
struct brw_vs_prog_key key;
|
||||
struct brw_vs_prog_data prog_data;
|
||||
struct brw_chipset chipset;
|
||||
|
||||
struct brw_vertex_shader *vp;
|
||||
|
||||
GLuint nr_inputs;
|
||||
GLuint nr_outputs;
|
||||
GLuint nr_immediates;
|
||||
GLfloat immediate[128][4];
|
||||
|
||||
GLboolean copy_edgeflag;
|
||||
|
||||
GLuint overflow_grf_start;
|
||||
GLuint overflow_count;
|
||||
|
||||
GLuint first_tmp;
|
||||
GLuint last_tmp;
|
||||
|
||||
struct brw_reg r0;
|
||||
struct brw_reg r1;
|
||||
struct brw_reg regs[TGSI_FILE_COUNT][128];
|
||||
struct brw_reg tmp;
|
||||
struct brw_reg stack;
|
||||
|
||||
struct {
|
||||
GLboolean used_in_src;
|
||||
struct brw_reg reg;
|
||||
} output_regs[128];
|
||||
|
||||
struct brw_reg userplane[6];
|
||||
|
||||
/** we may need up to 3 constants per instruction (if use_const_buffer) */
|
||||
struct {
|
||||
GLint index;
|
||||
struct brw_reg reg;
|
||||
} current_const[3];
|
||||
|
||||
struct brw_instruction *if_inst[MAX_IF_DEPTH];
|
||||
struct brw_instruction *loop_inst[MAX_LOOP_DEPTH];
|
||||
GLuint insn;
|
||||
GLuint if_depth;
|
||||
GLuint loop_depth;
|
||||
GLuint end_offset;
|
||||
|
||||
struct brw_indirect stack_index;
|
||||
};
|
||||
|
||||
|
||||
void brw_vs_emit( struct brw_vs_compile *c );
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
|
||||
#include "brw_debug.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_defines.h"
|
||||
|
||||
struct brw_vs_unit_key {
|
||||
unsigned int total_grf;
|
||||
unsigned int urb_entry_read_length;
|
||||
unsigned int curb_entry_read_length;
|
||||
|
||||
unsigned int curbe_offset;
|
||||
|
||||
unsigned int nr_urb_entries, urb_size;
|
||||
|
||||
unsigned int nr_surfaces;
|
||||
};
|
||||
|
||||
static void
|
||||
vs_unit_populate_key(struct brw_context *brw, struct brw_vs_unit_key *key)
|
||||
{
|
||||
memset(key, 0, sizeof(*key));
|
||||
|
||||
/* CACHE_NEW_VS_PROG */
|
||||
key->total_grf = brw->vs.prog_data->total_grf;
|
||||
key->urb_entry_read_length = brw->vs.prog_data->urb_read_length;
|
||||
key->curb_entry_read_length = brw->vs.prog_data->curb_read_length;
|
||||
|
||||
/* BRW_NEW_URB_FENCE */
|
||||
key->nr_urb_entries = brw->urb.nr_vs_entries;
|
||||
key->urb_size = brw->urb.vsize;
|
||||
|
||||
/* BRW_NEW_NR_VS_SURFACES */
|
||||
key->nr_surfaces = brw->vs.nr_surfaces;
|
||||
|
||||
/* PIPE_NEW_CLIP */
|
||||
if (brw->curr.ucp.nr) {
|
||||
/* Note that we read in the userclip planes as well, hence
|
||||
* clip_start:
|
||||
*/
|
||||
key->curbe_offset = brw->curbe.clip_start;
|
||||
}
|
||||
else {
|
||||
key->curbe_offset = brw->curbe.vs_start;
|
||||
}
|
||||
}
|
||||
|
||||
static enum pipe_error
|
||||
vs_unit_create_from_key(struct brw_context *brw,
|
||||
struct brw_vs_unit_key *key,
|
||||
struct brw_winsys_reloc *reloc,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
enum pipe_error ret;
|
||||
struct brw_vs_unit_state vs;
|
||||
int chipset_max_threads;
|
||||
|
||||
memset(&vs, 0, sizeof(vs));
|
||||
|
||||
vs.thread0.kernel_start_pointer = 0; /* reloc */
|
||||
vs.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
|
||||
vs.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
|
||||
/* Choosing multiple program flow means that we may get 2-vertex threads,
|
||||
* which will have the channel mask for dwords 4-7 enabled in the thread,
|
||||
* and those dwords will be written to the second URB handle when we
|
||||
* brw_urb_WRITE() results.
|
||||
*/
|
||||
vs.thread1.single_program_flow = 0;
|
||||
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
vs.thread1.binding_table_entry_count = 0; /* hardware requirement */
|
||||
else
|
||||
vs.thread1.binding_table_entry_count = key->nr_surfaces;
|
||||
|
||||
vs.thread3.urb_entry_read_length = key->urb_entry_read_length;
|
||||
vs.thread3.const_urb_entry_read_length = key->curb_entry_read_length;
|
||||
vs.thread3.dispatch_grf_start_reg = 1;
|
||||
vs.thread3.urb_entry_read_offset = 0;
|
||||
vs.thread3.const_urb_entry_read_offset = key->curbe_offset * 2;
|
||||
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
vs.thread4.nr_urb_entries = key->nr_urb_entries >> 2;
|
||||
else
|
||||
vs.thread4.nr_urb_entries = key->nr_urb_entries;
|
||||
|
||||
vs.thread4.urb_entry_allocation_size = key->urb_size - 1;
|
||||
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
chipset_max_threads = 72;
|
||||
else if (BRW_IS_G4X(brw))
|
||||
chipset_max_threads = 32;
|
||||
else
|
||||
chipset_max_threads = 16;
|
||||
|
||||
vs.thread4.max_threads = CLAMP(key->nr_urb_entries / 2,
|
||||
1, chipset_max_threads) - 1;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_SINGLE_THREAD)
|
||||
vs.thread4.max_threads = 0;
|
||||
|
||||
/* No samplers for ARB_vp programs:
|
||||
*/
|
||||
/* It has to be set to 0 for IGDNG
|
||||
*/
|
||||
vs.vs5.sampler_count = 0;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_STATS)
|
||||
vs.thread4.stats_enable = 1;
|
||||
|
||||
/* Vertex program always enabled:
|
||||
*/
|
||||
vs.vs6.vs_enable = 1;
|
||||
|
||||
ret = brw_upload_cache(&brw->cache, BRW_VS_UNIT,
|
||||
key, sizeof(*key),
|
||||
reloc, 1,
|
||||
&vs, sizeof(vs),
|
||||
NULL, NULL,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
static int prepare_vs_unit(struct brw_context *brw)
|
||||
{
|
||||
struct brw_vs_unit_key key;
|
||||
enum pipe_error ret;
|
||||
struct brw_winsys_reloc reloc[1];
|
||||
unsigned grf_reg_count;
|
||||
|
||||
vs_unit_populate_key(brw, &key);
|
||||
|
||||
grf_reg_count = (align(key.total_grf, 16) / 16 - 1);
|
||||
|
||||
/* Emit VS program relocation */
|
||||
make_reloc(&reloc[0],
|
||||
BRW_USAGE_STATE,
|
||||
grf_reg_count << 1,
|
||||
offsetof(struct brw_vs_unit_state, thread0),
|
||||
brw->vs.prog_bo);
|
||||
|
||||
|
||||
if (brw_search_cache(&brw->cache, BRW_VS_UNIT,
|
||||
&key, sizeof(key),
|
||||
reloc, 1,
|
||||
NULL,
|
||||
&brw->vs.state_bo))
|
||||
return PIPE_OK;
|
||||
|
||||
ret = vs_unit_create_from_key(brw, &key, reloc, &brw->vs.state_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_vs_unit = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_CLIP),
|
||||
.brw = (BRW_NEW_CURBE_OFFSETS |
|
||||
BRW_NEW_NR_VS_SURFACES |
|
||||
BRW_NEW_URB_FENCE),
|
||||
.cache = CACHE_NEW_VS_PROG
|
||||
},
|
||||
.prepare = prepare_vs_unit,
|
||||
};
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_winsys.h"
|
||||
|
||||
/* XXX: disabled true constant buffer functionality
|
||||
*/
|
||||
|
||||
|
||||
/* Creates a new VS constant buffer reflecting the current VS program's
|
||||
* constants, if needed by the VS program.
|
||||
*
|
||||
* Otherwise, constants go through the CURBEs using the brw_constant_buffer
|
||||
* state atom.
|
||||
*/
|
||||
#if 0
|
||||
static struct brw_winsys_buffer *
|
||||
brw_vs_update_constant_buffer(struct brw_context *brw)
|
||||
{
|
||||
/* XXX: true constant buffers
|
||||
*/
|
||||
struct brw_vertex_program *vp =
|
||||
(struct brw_vertex_program *) brw->vertex_program;
|
||||
const struct gl_program_parameter_list *params = vp->program.Base.Parameters;
|
||||
const int size = params->NumParameters * 4 * sizeof(GLfloat);
|
||||
drm_intel_bo *const_buffer;
|
||||
|
||||
/* BRW_NEW_VERTEX_PROGRAM */
|
||||
if (!vp->use_const_buffer)
|
||||
return NULL;
|
||||
|
||||
const_buffer = brw->sws->bo_alloc(brw->sws,
|
||||
BRW_BUFFER_TYPE_SHADER_CONSTANTS,
|
||||
size, 64);
|
||||
|
||||
/* _NEW_PROGRAM_CONSTANTS */
|
||||
brw->sws->bo_subdata(const_buffer, 0, size, params->ParameterValues,
|
||||
NULL, 0);
|
||||
|
||||
return const_buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Update the surface state for a VS constant buffer.
|
||||
*
|
||||
* Sets brw->vs.surf_bo[surf] and brw->vp->const_buffer.
|
||||
*/
|
||||
#if 0
|
||||
static void
|
||||
brw_update_vs_constant_surface( struct brw_context *brw,
|
||||
GLuint surf)
|
||||
{
|
||||
struct brw_surface_key key;
|
||||
struct pipe_buffer *cb = brw->curr.vs_constants;
|
||||
enum pipe_error ret;
|
||||
|
||||
assert(surf == 0);
|
||||
|
||||
/* If we're in this state update atom, we need to update VS constants, so
|
||||
* free the old buffer and create a new one for the new contents.
|
||||
*/
|
||||
ret = brw_vs_update_constant_buffer(brw, &vp->const_buffer);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If there's no constant buffer, then no surface BO is needed to point at
|
||||
* it.
|
||||
*/
|
||||
if (vp->const_buffer == NULL) {
|
||||
bo_reference(brw->vs.surf_bo[surf], NULL);
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
|
||||
key.format = PIPE_FORMAT_R32G32B32A32_FLOAT;
|
||||
key.bo = vp->const_buffer;
|
||||
key.depthmode = GL_NONE;
|
||||
key.pitch = params->NumParameters;
|
||||
key.width = params->NumParameters;
|
||||
key.height = 1;
|
||||
key.depth = 1;
|
||||
key.cpp = 16;
|
||||
|
||||
/*
|
||||
printf("%s:\n", __FUNCTION__);
|
||||
printf(" width %d height %d depth %d cpp %d pitch %d\n",
|
||||
key.width, key.height, key.depth, key.cpp, key.pitch);
|
||||
*/
|
||||
|
||||
if (brw_search_cache(&brw->surface_cache,
|
||||
BRW_SS_SURFACE,
|
||||
&key, sizeof(key),
|
||||
&key.bo, key.bo ? 1 : 0,
|
||||
NULL,
|
||||
&brw->vs.surf_bo[surf]))
|
||||
return PIPE_OK;
|
||||
|
||||
ret = brw_create_constant_surface(brw, &key
|
||||
&brw->vs.surf_bo[surf]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Constructs the binding table for the VS surface state.
|
||||
*/
|
||||
static enum pipe_error
|
||||
brw_vs_get_binding_table(struct brw_context *brw,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
#if 0
|
||||
static GLuint data[BRW_VS_MAX_SURF]; /* always zero */
|
||||
struct brw_winsys_reloc reloc[BRW_VS_MAX_SURF];
|
||||
int i;
|
||||
|
||||
/* Emit binding table relocations to surface state */
|
||||
for (i = 0; i < BRW_VS_MAX_SURF; i++) {
|
||||
make_reloc(&reloc[i],
|
||||
BRW_USAGE_STATE,
|
||||
0,
|
||||
i * 4,
|
||||
brw->vs.surf_bo[i]);
|
||||
}
|
||||
|
||||
ret = brw_cache_data( &brw->surface_cache,
|
||||
BRW_SS_SURF_BIND,
|
||||
NULL, 0,
|
||||
reloc, nr_reloc,
|
||||
data, sizeof data,
|
||||
NULL, NULL,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
FREE(data);
|
||||
return PIPE_OK;
|
||||
#else
|
||||
return PIPE_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Vertex shader surfaces (constant buffer).
|
||||
*
|
||||
* This consumes the state updates for the constant buffer needing
|
||||
* to be updated, and produces BRW_NEW_NR_VS_SURFACES for the VS unit and
|
||||
* CACHE_NEW_SURF_BIND for the binding table upload.
|
||||
*/
|
||||
static enum pipe_error prepare_vs_surfaces(struct brw_context *brw )
|
||||
{
|
||||
enum pipe_error ret;
|
||||
|
||||
#if 0
|
||||
int i;
|
||||
int nr_surfaces = 0;
|
||||
|
||||
brw_update_vs_constant_surface(ctx, SURF_INDEX_VERT_CONST_BUFFER);
|
||||
|
||||
for (i = 0; i < BRW_VS_MAX_SURF; i++) {
|
||||
if (brw->vs.surf_bo[i] != NULL) {
|
||||
nr_surfaces = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (brw->vs.nr_surfaces != nr_surfaces) {
|
||||
brw->state.dirty.brw |= BRW_NEW_NR_VS_SURFACES;
|
||||
brw->vs.nr_surfaces = nr_surfaces;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Note that we don't end up updating the bind_bo if we don't have a
|
||||
* surface to be pointing at. This should be relatively harmless, as it
|
||||
* just slightly increases our working set size.
|
||||
*/
|
||||
if (brw->vs.nr_surfaces != 0) {
|
||||
ret = brw_vs_get_binding_table(brw, &brw->vs.bind_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_vs_surfaces = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_VERTEX_CONSTANTS |
|
||||
PIPE_NEW_VERTEX_SHADER),
|
||||
.brw = 0,
|
||||
.cache = 0
|
||||
},
|
||||
.prepare = prepare_vs_surfaces,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright © 2009 Jakob Bornecrantz
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef BRW_WINSYS_H
|
||||
#define BRW_WINSYS_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_refcnt.h"
|
||||
|
||||
struct brw_winsys;
|
||||
struct pipe_fence_handle;
|
||||
|
||||
/* Not sure why the winsys needs this:
|
||||
*/
|
||||
#define BRW_BATCH_SIZE (32*1024)
|
||||
|
||||
struct brw_winsys_screen;
|
||||
|
||||
/* Need a tiny bit of information inside the abstract buffer struct:
|
||||
*/
|
||||
struct brw_winsys_buffer {
|
||||
struct pipe_reference reference;
|
||||
struct brw_winsys_screen *sws;
|
||||
unsigned size;
|
||||
};
|
||||
|
||||
|
||||
/* Should be possible to validate usages above against buffer creation
|
||||
* types, below:
|
||||
*/
|
||||
enum brw_buffer_type
|
||||
{
|
||||
BRW_BUFFER_TYPE_TEXTURE,
|
||||
BRW_BUFFER_TYPE_SCANOUT, /**< a texture used for scanning out from */
|
||||
BRW_BUFFER_TYPE_VERTEX,
|
||||
BRW_BUFFER_TYPE_CURBE,
|
||||
BRW_BUFFER_TYPE_QUERY,
|
||||
BRW_BUFFER_TYPE_SHADER_CONSTANTS,
|
||||
BRW_BUFFER_TYPE_SHADER_SCRATCH,
|
||||
BRW_BUFFER_TYPE_BATCH,
|
||||
BRW_BUFFER_TYPE_GENERAL_STATE,
|
||||
BRW_BUFFER_TYPE_SURFACE_STATE,
|
||||
BRW_BUFFER_TYPE_PIXEL, /* image uploads, pbo's, etc */
|
||||
BRW_BUFFER_TYPE_GENERIC, /* unknown */
|
||||
BRW_BUFFER_TYPE_MAX /* Count of possible values */
|
||||
};
|
||||
|
||||
|
||||
/* Describe the usage of a particular buffer in a relocation. The DRM
|
||||
* winsys will translate these back to GEM read/write domain flags.
|
||||
*/
|
||||
enum brw_buffer_usage {
|
||||
BRW_USAGE_STATE, /* INSTRUCTION, 0 */
|
||||
BRW_USAGE_QUERY_RESULT, /* INSTRUCTION, INSTRUCTION */
|
||||
BRW_USAGE_RENDER_TARGET, /* RENDER, 0 */
|
||||
BRW_USAGE_DEPTH_BUFFER, /* RENDER, RENDER */
|
||||
BRW_USAGE_BLIT_SOURCE, /* RENDER, 0 */
|
||||
BRW_USAGE_BLIT_DEST, /* RENDER, RENDER */
|
||||
BRW_USAGE_SAMPLER, /* SAMPLER, 0 */
|
||||
BRW_USAGE_VERTEX, /* VERTEX, 0 */
|
||||
BRW_USAGE_SCRATCH, /* 0, 0 */
|
||||
BRW_USAGE_MAX
|
||||
};
|
||||
|
||||
enum brw_buffer_data_type {
|
||||
BRW_DATA_GS_CC_VP,
|
||||
BRW_DATA_GS_CC_UNIT,
|
||||
BRW_DATA_GS_WM_PROG,
|
||||
BRW_DATA_GS_SAMPLER_DEFAULT_COLOR,
|
||||
BRW_DATA_GS_SAMPLER,
|
||||
BRW_DATA_GS_WM_UNIT,
|
||||
BRW_DATA_GS_SF_PROG,
|
||||
BRW_DATA_GS_SF_VP,
|
||||
BRW_DATA_GS_SF_UNIT,
|
||||
BRW_DATA_GS_VS_UNIT,
|
||||
BRW_DATA_GS_VS_PROG,
|
||||
BRW_DATA_GS_GS_UNIT,
|
||||
BRW_DATA_GS_GS_PROG,
|
||||
BRW_DATA_GS_CLIP_VP,
|
||||
BRW_DATA_GS_CLIP_UNIT,
|
||||
BRW_DATA_GS_CLIP_PROG,
|
||||
BRW_DATA_SS_SURFACE,
|
||||
BRW_DATA_SS_SURF_BIND,
|
||||
BRW_DATA_CONSTANT_BUFFER,
|
||||
BRW_DATA_BATCH_BUFFER,
|
||||
BRW_DATA_OTHER,
|
||||
BRW_DATA_MAX
|
||||
};
|
||||
|
||||
|
||||
/* Matches the i915_drm definitions:
|
||||
*/
|
||||
#define BRW_TILING_NONE 0
|
||||
#define BRW_TILING_X 1
|
||||
#define BRW_TILING_Y 2
|
||||
|
||||
|
||||
/* Relocations to be applied with subdata in a call to sws->bo_subdata, below.
|
||||
*
|
||||
* Effectively this encodes:
|
||||
*
|
||||
* (unsigned *)(subdata + offset) = bo->offset + delta
|
||||
*/
|
||||
struct brw_winsys_reloc {
|
||||
enum brw_buffer_usage usage; /* debug only */
|
||||
unsigned delta;
|
||||
unsigned offset;
|
||||
struct brw_winsys_buffer *bo;
|
||||
};
|
||||
|
||||
static INLINE void make_reloc(struct brw_winsys_reloc *reloc,
|
||||
enum brw_buffer_usage usage,
|
||||
unsigned delta,
|
||||
unsigned offset,
|
||||
struct brw_winsys_buffer *bo)
|
||||
{
|
||||
reloc->usage = usage;
|
||||
reloc->delta = delta;
|
||||
reloc->offset = offset;
|
||||
reloc->bo = bo; /* Note - note taking a reference yet */
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct brw_winsys_screen {
|
||||
|
||||
|
||||
/**
|
||||
* Buffer functions.
|
||||
*/
|
||||
|
||||
/*@{*/
|
||||
/**
|
||||
* Create a buffer.
|
||||
*/
|
||||
enum pipe_error (*bo_alloc)(struct brw_winsys_screen *sws,
|
||||
enum brw_buffer_type type,
|
||||
unsigned size,
|
||||
unsigned alignment,
|
||||
struct brw_winsys_buffer **bo_out);
|
||||
|
||||
/* Destroy a buffer when our refcount goes to zero:
|
||||
*/
|
||||
void (*bo_destroy)(struct brw_winsys_buffer *buffer);
|
||||
|
||||
/* delta -- added to b2->offset, and written into buffer
|
||||
* offset -- location above value is written to within buffer
|
||||
*/
|
||||
enum pipe_error (*bo_emit_reloc)(struct brw_winsys_buffer *buffer,
|
||||
enum brw_buffer_usage usage,
|
||||
unsigned delta,
|
||||
unsigned offset,
|
||||
struct brw_winsys_buffer *b2);
|
||||
|
||||
enum pipe_error (*bo_exec)(struct brw_winsys_buffer *buffer,
|
||||
unsigned bytes_used);
|
||||
|
||||
enum pipe_error (*bo_subdata)(struct brw_winsys_buffer *buffer,
|
||||
enum brw_buffer_data_type data_type,
|
||||
size_t offset,
|
||||
size_t size,
|
||||
const void *data,
|
||||
const struct brw_winsys_reloc *reloc,
|
||||
unsigned nr_reloc );
|
||||
|
||||
boolean (*bo_is_busy)(struct brw_winsys_buffer *buffer);
|
||||
boolean (*bo_references)(struct brw_winsys_buffer *a,
|
||||
struct brw_winsys_buffer *b);
|
||||
|
||||
/* XXX: couldn't this be handled by returning true/false on
|
||||
* bo_emit_reloc?
|
||||
*/
|
||||
enum pipe_error (*check_aperture_space)(struct brw_winsys_screen *iws,
|
||||
struct brw_winsys_buffer **buffers,
|
||||
unsigned count);
|
||||
|
||||
/**
|
||||
* Map a buffer.
|
||||
*/
|
||||
void *(*bo_map)(struct brw_winsys_buffer *buffer,
|
||||
enum brw_buffer_data_type data_type,
|
||||
unsigned offset,
|
||||
unsigned length,
|
||||
boolean write,
|
||||
boolean discard,
|
||||
boolean flush_explicit);
|
||||
|
||||
void (*bo_flush_range)(struct brw_winsys_buffer *buffer,
|
||||
unsigned offset,
|
||||
unsigned length);
|
||||
|
||||
/**
|
||||
* Unmap a buffer.
|
||||
*/
|
||||
void (*bo_unmap)(struct brw_winsys_buffer *buffer);
|
||||
/*@}*/
|
||||
|
||||
|
||||
/* Wait for buffer to go idle. Similar to map+unmap, but doesn't
|
||||
* mark buffer contents as dirty.
|
||||
*/
|
||||
void (*bo_wait_idle)(struct brw_winsys_buffer *buffer);
|
||||
|
||||
/**
|
||||
* Destroy the winsys.
|
||||
*/
|
||||
void (*destroy)(struct brw_winsys_screen *iws);
|
||||
};
|
||||
|
||||
static INLINE void *
|
||||
bo_map_read(struct brw_winsys_screen *sws, struct brw_winsys_buffer *buf)
|
||||
{
|
||||
return sws->bo_map( buf,
|
||||
BRW_DATA_OTHER,
|
||||
0, buf->size,
|
||||
FALSE, FALSE, FALSE );
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
bo_reference(struct brw_winsys_buffer **ptr, struct brw_winsys_buffer *buf)
|
||||
{
|
||||
struct brw_winsys_buffer *old_buf = *ptr;
|
||||
|
||||
if (pipe_reference((struct pipe_reference **)ptr, &buf->reference))
|
||||
old_buf->sws->bo_destroy(old_buf);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create brw pipe_screen.
|
||||
*/
|
||||
struct pipe_screen *brw_create_screen(struct brw_winsys_screen *iws, unsigned pci_id);
|
||||
|
||||
/**
|
||||
* Create a brw pipe_context.
|
||||
*/
|
||||
struct pipe_context *brw_create_context(struct pipe_screen *screen);
|
||||
|
||||
/**
|
||||
* Get the brw_winsys buffer backing the texture.
|
||||
*
|
||||
* TODO UGLY
|
||||
*/
|
||||
struct pipe_texture;
|
||||
boolean brw_texture_get_winsys_buffer(struct pipe_texture *texture,
|
||||
struct brw_winsys_buffer **buffer,
|
||||
unsigned *stride);
|
||||
|
||||
/**
|
||||
* Wrap a brw_winsys buffer with a texture blanket.
|
||||
*
|
||||
* TODO UGLY
|
||||
*/
|
||||
struct pipe_texture *
|
||||
brw_texture_blanket_winsys_buffer(struct pipe_screen *screen,
|
||||
const struct pipe_texture *template,
|
||||
unsigned pitch,
|
||||
unsigned tiling,
|
||||
struct brw_winsys_buffer *buffer);
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Cooperative dumping between winsys and driver. TODO: make this
|
||||
* driver-only by wrapping calls to winsys->bo_subdata().
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
extern int BRW_DUMP;
|
||||
#else
|
||||
#define BRW_DUMP 0
|
||||
#endif
|
||||
|
||||
#define DUMP_ASM 0x1
|
||||
#define DUMP_STATE 0x2
|
||||
#define DUMP_BATCH 0x4
|
||||
|
||||
void brw_dump_data( unsigned pci_id,
|
||||
enum brw_buffer_data_type data_type,
|
||||
unsigned offset,
|
||||
const void *data,
|
||||
size_t size );
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
#include "brw_winsys.h"
|
||||
#include "brw_disasm.h"
|
||||
#include "brw_structs_dump.h"
|
||||
#include "brw_structs.h"
|
||||
#include "intel_decode.h"
|
||||
|
||||
|
||||
void brw_dump_data( unsigned pci_id,
|
||||
enum brw_buffer_data_type data_type,
|
||||
unsigned offset,
|
||||
const void *data,
|
||||
size_t size )
|
||||
{
|
||||
if (BRW_DUMP & DUMP_ASM) {
|
||||
switch (data_type) {
|
||||
case BRW_DATA_GS_WM_PROG:
|
||||
case BRW_DATA_GS_SF_PROG:
|
||||
case BRW_DATA_GS_VS_PROG:
|
||||
case BRW_DATA_GS_GS_PROG:
|
||||
case BRW_DATA_GS_CLIP_PROG:
|
||||
brw_disasm( stderr, data, size / sizeof(struct brw_instruction) );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (BRW_DUMP & DUMP_STATE) {
|
||||
switch (data_type) {
|
||||
case BRW_DATA_GS_CC_VP:
|
||||
brw_dump_cc_viewport( data );
|
||||
break;
|
||||
case BRW_DATA_GS_CC_UNIT:
|
||||
brw_dump_cc_unit_state( data );
|
||||
break;
|
||||
case BRW_DATA_GS_SAMPLER_DEFAULT_COLOR:
|
||||
brw_dump_sampler_default_color( data );
|
||||
break;
|
||||
case BRW_DATA_GS_SAMPLER:
|
||||
brw_dump_sampler_state( data );
|
||||
break;
|
||||
case BRW_DATA_GS_WM_UNIT:
|
||||
brw_dump_wm_unit_state( data );
|
||||
break;
|
||||
case BRW_DATA_GS_SF_VP:
|
||||
brw_dump_sf_viewport( data );
|
||||
break;
|
||||
case BRW_DATA_GS_SF_UNIT:
|
||||
brw_dump_sf_unit_state( data );
|
||||
break;
|
||||
case BRW_DATA_GS_VS_UNIT:
|
||||
brw_dump_vs_unit_state( data );
|
||||
break;
|
||||
case BRW_DATA_GS_GS_UNIT:
|
||||
brw_dump_gs_unit_state( data );
|
||||
break;
|
||||
case BRW_DATA_GS_CLIP_VP:
|
||||
brw_dump_clipper_viewport( data );
|
||||
break;
|
||||
case BRW_DATA_GS_CLIP_UNIT:
|
||||
brw_dump_clip_unit_state( data );
|
||||
break;
|
||||
case BRW_DATA_SS_SURFACE:
|
||||
brw_dump_surface_state( data );
|
||||
break;
|
||||
case BRW_DATA_SS_SURF_BIND:
|
||||
break;
|
||||
case BRW_DATA_OTHER:
|
||||
break;
|
||||
case BRW_DATA_CONSTANT_BUFFER:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (BRW_DUMP & DUMP_BATCH) {
|
||||
switch (data_type) {
|
||||
case BRW_DATA_BATCH_BUFFER:
|
||||
intel_decode(data, size / 4, offset, pci_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
#include "tgsi/tgsi_info.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_screen.h"
|
||||
#include "brw_util.h"
|
||||
#include "brw_wm.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_debug.h"
|
||||
#include "brw_pipe_rast.h"
|
||||
|
||||
|
||||
/** Return number of src args for given instruction */
|
||||
GLuint brw_wm_nr_args( GLuint opcode )
|
||||
{
|
||||
switch (opcode) {
|
||||
case WM_FRONTFACING:
|
||||
case WM_PIXELXY:
|
||||
return 0;
|
||||
case WM_CINTERP:
|
||||
case WM_WPOSXY:
|
||||
case WM_DELTAXY:
|
||||
return 1;
|
||||
case WM_LINTERP:
|
||||
case WM_PIXELW:
|
||||
return 2;
|
||||
case WM_FB_WRITE:
|
||||
case WM_PINTERP:
|
||||
return 3;
|
||||
case TGSI_OPCODE_TEX:
|
||||
case TGSI_OPCODE_TXP:
|
||||
case TGSI_OPCODE_TXB:
|
||||
case TGSI_OPCODE_TXD:
|
||||
/* sampler arg is held as a field in the instruction, not in an
|
||||
* actual register:
|
||||
*/
|
||||
return tgsi_get_opcode_info(opcode)->num_src - 1;
|
||||
|
||||
default:
|
||||
assert(opcode < MAX_OPCODE);
|
||||
return tgsi_get_opcode_info(opcode)->num_src;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLuint brw_wm_is_scalar_result( GLuint opcode )
|
||||
{
|
||||
switch (opcode) {
|
||||
case TGSI_OPCODE_COS:
|
||||
case TGSI_OPCODE_EX2:
|
||||
case TGSI_OPCODE_LG2:
|
||||
case TGSI_OPCODE_POW:
|
||||
case TGSI_OPCODE_RCP:
|
||||
case TGSI_OPCODE_RSQ:
|
||||
case TGSI_OPCODE_SIN:
|
||||
case TGSI_OPCODE_DP3:
|
||||
case TGSI_OPCODE_DP4:
|
||||
case TGSI_OPCODE_DPH:
|
||||
case TGSI_OPCODE_DST:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do GPU code generation for shaders without flow control. Shaders
|
||||
* without flow control instructions can more readily be analysed for
|
||||
* SSA-style optimizations.
|
||||
*/
|
||||
static void
|
||||
brw_wm_linear_shader_emit(struct brw_context *brw, struct brw_wm_compile *c)
|
||||
{
|
||||
/* Augment fragment program. Add instructions for pre- and
|
||||
* post-fragment-program tasks such as interpolation and fogging.
|
||||
*/
|
||||
brw_wm_pass_fp(c);
|
||||
|
||||
/* Translate to intermediate representation. Build register usage
|
||||
* chains.
|
||||
*/
|
||||
brw_wm_pass0(c);
|
||||
|
||||
/* Dead code removal.
|
||||
*/
|
||||
brw_wm_pass1(c);
|
||||
|
||||
/* Register allocation.
|
||||
* Divide by two because we operate on 16 pixels at a time and require
|
||||
* two GRF entries for each logical shader register.
|
||||
*/
|
||||
c->grf_limit = BRW_WM_MAX_GRF / 2;
|
||||
|
||||
brw_wm_pass2(c);
|
||||
|
||||
/* how many general-purpose registers are used */
|
||||
c->prog_data.total_grf = c->max_wm_grf;
|
||||
|
||||
/* Scratch space is used for register spilling */
|
||||
if (c->last_scratch) {
|
||||
c->prog_data.total_scratch = c->last_scratch + 0x40;
|
||||
}
|
||||
else {
|
||||
c->prog_data.total_scratch = 0;
|
||||
}
|
||||
|
||||
/* Emit GEN4 code.
|
||||
*/
|
||||
brw_wm_emit(c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* All Mesa program -> GPU code generation goes through this function.
|
||||
* Depending on the instructions used (i.e. flow control instructions)
|
||||
* we'll use one of two code generators.
|
||||
*/
|
||||
static enum pipe_error do_wm_prog( struct brw_context *brw,
|
||||
struct brw_fragment_shader *fp,
|
||||
struct brw_wm_prog_key *key,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
enum pipe_error ret;
|
||||
struct brw_wm_compile *c;
|
||||
const GLuint *program;
|
||||
GLuint program_size;
|
||||
|
||||
if (brw->wm.compile_data == NULL) {
|
||||
brw->wm.compile_data = MALLOC(sizeof(*brw->wm.compile_data));
|
||||
if (!brw->wm.compile_data)
|
||||
return PIPE_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
c = brw->wm.compile_data;
|
||||
memset(c, 0, sizeof *c);
|
||||
|
||||
c->key = *key;
|
||||
c->fp = fp;
|
||||
c->env_param = NULL; /*brw->intel.ctx.FragmentProgram.Parameters;*/
|
||||
|
||||
brw_init_compile(brw, &c->func);
|
||||
|
||||
/*
|
||||
* Shader which use GLSL features such as flow control are handled
|
||||
* differently from "simple" shaders.
|
||||
*/
|
||||
if (fp->has_flow_control) {
|
||||
c->dispatch_width = 8;
|
||||
/* XXX: GLSL support
|
||||
*/
|
||||
exit(1);
|
||||
/* brw_wm_branching_shader_emit(brw, c); */
|
||||
}
|
||||
else {
|
||||
c->dispatch_width = 16;
|
||||
brw_wm_linear_shader_emit(brw, c);
|
||||
}
|
||||
|
||||
if (BRW_DEBUG & DEBUG_WM)
|
||||
debug_printf("\n");
|
||||
|
||||
/* get the program
|
||||
*/
|
||||
ret = brw_get_program(&c->func, &program, &program_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = brw_upload_cache( &brw->cache, BRW_WM_PROG,
|
||||
&c->key, sizeof(c->key),
|
||||
NULL, 0,
|
||||
program, program_size,
|
||||
&c->prog_data,
|
||||
&brw->wm.prog_data,
|
||||
bo_out );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void brw_wm_populate_key( struct brw_context *brw,
|
||||
struct brw_wm_prog_key *key )
|
||||
{
|
||||
unsigned lookup, line_aa;
|
||||
unsigned i;
|
||||
|
||||
memset(key, 0, sizeof(*key));
|
||||
|
||||
/* PIPE_NEW_FRAGMENT_SHADER
|
||||
* PIPE_NEW_DEPTH_STENCIL_ALPHA
|
||||
*/
|
||||
lookup = (brw->curr.zstencil->iz_lookup |
|
||||
brw->curr.fragment_shader->iz_lookup);
|
||||
|
||||
|
||||
/* PIPE_NEW_RAST
|
||||
* BRW_NEW_REDUCED_PRIMITIVE
|
||||
*/
|
||||
switch (brw->reduced_primitive) {
|
||||
case PIPE_PRIM_POINTS:
|
||||
line_aa = AA_NEVER;
|
||||
break;
|
||||
case PIPE_PRIM_LINES:
|
||||
line_aa = (brw->curr.rast->templ.line_smooth ?
|
||||
AA_ALWAYS : AA_NEVER);
|
||||
break;
|
||||
default:
|
||||
line_aa = brw->curr.rast->unfilled_aa_line;
|
||||
break;
|
||||
}
|
||||
|
||||
brw_wm_lookup_iz(line_aa,
|
||||
lookup,
|
||||
brw->curr.fragment_shader->uses_depth,
|
||||
key);
|
||||
|
||||
/* PIPE_NEW_RAST */
|
||||
key->flat_shade = brw->curr.rast->templ.flatshade;
|
||||
|
||||
|
||||
/* PIPE_NEW_BOUND_TEXTURES */
|
||||
for (i = 0; i < brw->curr.num_textures; i++) {
|
||||
const struct brw_texture *tex = brw_texture(brw->curr.texture[i]);
|
||||
|
||||
if (tex->base.format == PIPE_FORMAT_YCBCR)
|
||||
key->yuvtex_mask |= 1 << i;
|
||||
|
||||
if (tex->base.format == PIPE_FORMAT_YCBCR_REV)
|
||||
key->yuvtex_swap_mask |= 1 << i;
|
||||
|
||||
/* XXX: shadow texture
|
||||
*/
|
||||
/* key->shadowtex_mask |= 1<<i; */
|
||||
}
|
||||
|
||||
/* CACHE_NEW_VS_PROG */
|
||||
key->vp_nr_outputs = brw->vs.prog_data->nr_outputs;
|
||||
|
||||
key->nr_cbufs = brw->curr.fb.nr_cbufs;
|
||||
|
||||
key->nr_inputs = brw->curr.fragment_shader->info.num_inputs;
|
||||
|
||||
/* The unique fragment program ID */
|
||||
key->program_string_id = brw->curr.fragment_shader->id;
|
||||
}
|
||||
|
||||
|
||||
static enum pipe_error brw_prepare_wm_prog(struct brw_context *brw)
|
||||
{
|
||||
struct brw_wm_prog_key key;
|
||||
struct brw_fragment_shader *fs = brw->curr.fragment_shader;
|
||||
enum pipe_error ret;
|
||||
|
||||
brw_wm_populate_key(brw, &key);
|
||||
|
||||
/* Make an early check for the key.
|
||||
*/
|
||||
if (brw_search_cache(&brw->cache, BRW_WM_PROG,
|
||||
&key, sizeof(key),
|
||||
NULL, 0,
|
||||
&brw->wm.prog_data,
|
||||
&brw->wm.prog_bo))
|
||||
return PIPE_OK;
|
||||
|
||||
ret = do_wm_prog(brw, fs, &key, &brw->wm.prog_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
const struct brw_tracked_state brw_wm_prog = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_FRAGMENT_SHADER |
|
||||
PIPE_NEW_DEPTH_STENCIL_ALPHA |
|
||||
PIPE_NEW_RAST |
|
||||
PIPE_NEW_NR_CBUFS |
|
||||
PIPE_NEW_BOUND_TEXTURES),
|
||||
.brw = (BRW_NEW_WM_INPUT_DIMENSIONS |
|
||||
BRW_NEW_REDUCED_PRIMITIVE),
|
||||
.cache = CACHE_NEW_VS_PROG,
|
||||
},
|
||||
.prepare = brw_prepare_wm_prog
|
||||
};
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BRW_WM_H
|
||||
#define BRW_WM_H
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_eu.h"
|
||||
|
||||
#define SATURATE (1<<5)
|
||||
|
||||
/* A big lookup table is used to figure out which and how many
|
||||
* additional regs will inserted before the main payload in the WM
|
||||
* program execution. These mainly relate to depth and stencil
|
||||
* processing and the early-depth-test optimization.
|
||||
*/
|
||||
#define IZ_PS_KILL_ALPHATEST_BIT 0x1
|
||||
#define IZ_PS_COMPUTES_DEPTH_BIT 0x2
|
||||
#define IZ_DEPTH_WRITE_ENABLE_BIT 0x4
|
||||
#define IZ_DEPTH_TEST_ENABLE_BIT 0x8
|
||||
#define IZ_STENCIL_WRITE_ENABLE_BIT 0x10
|
||||
#define IZ_STENCIL_TEST_ENABLE_BIT 0x20
|
||||
#define IZ_BIT_MAX 0x40
|
||||
|
||||
#define AA_NEVER 0
|
||||
#define AA_SOMETIMES 1
|
||||
#define AA_ALWAYS 2
|
||||
|
||||
struct brw_wm_prog_key {
|
||||
GLuint source_depth_reg:3;
|
||||
GLuint aa_dest_stencil_reg:3;
|
||||
GLuint dest_depth_reg:3;
|
||||
GLuint nr_depth_regs:3;
|
||||
GLuint computes_depth:1;
|
||||
GLuint source_depth_to_render_target:1;
|
||||
GLuint flat_shade:1;
|
||||
GLuint runtime_check_aads_emit:1;
|
||||
|
||||
GLuint shadowtex_mask:16;
|
||||
GLuint yuvtex_mask:16;
|
||||
GLuint yuvtex_swap_mask:16; /* UV swaped */
|
||||
|
||||
GLuint vp_nr_outputs:6;
|
||||
GLuint nr_inputs:6;
|
||||
GLuint nr_cbufs:3;
|
||||
GLuint has_flow_control:1;
|
||||
|
||||
GLuint program_string_id;
|
||||
};
|
||||
|
||||
|
||||
/* A bit of a glossary:
|
||||
*
|
||||
* brw_wm_value: A computed value or program input. Values are
|
||||
* constant, they are created once and are never modified. When a
|
||||
* fragment program register is written or overwritten, new values are
|
||||
* created fresh, preserving the rule that values are constant.
|
||||
*
|
||||
* brw_wm_ref: A reference to a value. Wherever a value used is by an
|
||||
* instruction or as a program output, that is tracked with an
|
||||
* instance of this struct. All references to a value occur after it
|
||||
* is created. After the last reference, a value is dead and can be
|
||||
* discarded.
|
||||
*
|
||||
* brw_wm_grf: Represents a physical hardware register. May be either
|
||||
* empty or hold a value. Register allocation is the process of
|
||||
* assigning values to grf registers. This occurs in pass2 and the
|
||||
* brw_wm_grf struct is not used before that.
|
||||
*
|
||||
* Fragment program registers: These are time-varying constructs that
|
||||
* are hard to reason about and which we translate away in pass0. A
|
||||
* single fragment program register element (eg. temp[0].x) will be
|
||||
* translated to one or more brw_wm_value structs, one for each time
|
||||
* that temp[0].x is written to during the program.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Used in pass2 to track register allocation.
|
||||
*/
|
||||
struct brw_wm_grf {
|
||||
struct brw_wm_value *value;
|
||||
GLuint nextuse;
|
||||
};
|
||||
|
||||
struct brw_wm_value {
|
||||
struct brw_reg hw_reg; /* emitted to this reg, may not always be there */
|
||||
struct brw_wm_ref *lastuse;
|
||||
struct brw_wm_grf *resident;
|
||||
GLuint contributes_to_output:1;
|
||||
GLuint spill_slot:16; /* if non-zero, spill immediately after calculation */
|
||||
};
|
||||
|
||||
struct brw_wm_ref {
|
||||
struct brw_reg hw_reg; /* nr filled in in pass2, everything else, pass0 */
|
||||
struct brw_wm_value *value;
|
||||
struct brw_wm_ref *prevuse;
|
||||
GLuint unspill_reg:7; /* unspill to reg */
|
||||
GLuint emitted:1;
|
||||
GLuint insn:24;
|
||||
};
|
||||
|
||||
struct brw_wm_instruction {
|
||||
struct brw_wm_value *dst[4];
|
||||
struct brw_wm_ref *src[3][4];
|
||||
GLuint opcode:8;
|
||||
GLuint saturate:1;
|
||||
GLuint writemask:4;
|
||||
GLuint sampler:4;
|
||||
GLuint tex_unit:4; /* texture/sampler unit for texture instructions */
|
||||
GLuint target:4; /* TGSI_TEXTURE_x for texture instructions,
|
||||
* target binding table index for FB_WRITE
|
||||
*/
|
||||
GLuint eot:1; /* End of thread indicator for FB_WRITE*/
|
||||
};
|
||||
|
||||
|
||||
#define BRW_WM_MAX_INSN 2048
|
||||
#define BRW_WM_MAX_GRF 128 /* hardware limit */
|
||||
#define BRW_WM_MAX_VREG (BRW_WM_MAX_INSN * 4)
|
||||
#define BRW_WM_MAX_REF (BRW_WM_MAX_INSN * 12)
|
||||
#define BRW_WM_MAX_PARAM 256
|
||||
#define BRW_WM_MAX_CONST 256
|
||||
#define BRW_WM_MAX_KILLS MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS
|
||||
#define BRW_WM_MAX_SUBROUTINE 16
|
||||
|
||||
|
||||
/* New opcodes to track internal operations required for WM unit.
|
||||
* These are added early so that the registers used can be tracked,
|
||||
* freed and reused like those of other instructions.
|
||||
*/
|
||||
#define MAX_OPCODE TGSI_OPCODE_LAST
|
||||
#define WM_PIXELXY (MAX_OPCODE)
|
||||
#define WM_DELTAXY (MAX_OPCODE + 1)
|
||||
#define WM_PIXELW (MAX_OPCODE + 2)
|
||||
#define WM_LINTERP (MAX_OPCODE + 3)
|
||||
#define WM_PINTERP (MAX_OPCODE + 4)
|
||||
#define WM_CINTERP (MAX_OPCODE + 5)
|
||||
#define WM_WPOSXY (MAX_OPCODE + 6)
|
||||
#define WM_FB_WRITE (MAX_OPCODE + 7)
|
||||
#define WM_FRONTFACING (MAX_OPCODE + 8)
|
||||
#define MAX_WM_OPCODE (MAX_OPCODE + 9)
|
||||
|
||||
#define BRW_FILE_PAYLOAD (TGSI_FILE_COUNT)
|
||||
#define PAYLOAD_DEPTH (PIPE_MAX_SHADER_INPUTS) /* ?? */
|
||||
|
||||
#define X 0
|
||||
#define Y 1
|
||||
#define Z 2
|
||||
#define W 3
|
||||
|
||||
|
||||
struct brw_fp_src {
|
||||
unsigned file:4;
|
||||
unsigned index:16;
|
||||
unsigned swizzle:8;
|
||||
unsigned indirect:1;
|
||||
unsigned negate:1;
|
||||
unsigned abs:1;
|
||||
};
|
||||
|
||||
struct brw_fp_dst {
|
||||
unsigned file:4;
|
||||
unsigned index:16;
|
||||
unsigned writemask:4;
|
||||
unsigned indirect:1;
|
||||
unsigned saturate:1;
|
||||
};
|
||||
|
||||
struct brw_fp_instruction {
|
||||
struct brw_fp_dst dst;
|
||||
struct brw_fp_src src[3];
|
||||
unsigned opcode:8;
|
||||
unsigned target:8; /* XXX: special usage for FB_WRITE */
|
||||
unsigned tex_unit:4;
|
||||
unsigned sampler:4;
|
||||
unsigned pad:8;
|
||||
};
|
||||
|
||||
|
||||
struct brw_wm_compile {
|
||||
struct brw_compile func;
|
||||
struct brw_wm_prog_key key;
|
||||
struct brw_wm_prog_data prog_data;
|
||||
|
||||
struct brw_fragment_shader *fp;
|
||||
|
||||
GLfloat (*env_param)[4];
|
||||
|
||||
enum {
|
||||
START,
|
||||
PASS2_DONE
|
||||
} state;
|
||||
|
||||
/* Initial pass - translate fp instructions to fp instructions,
|
||||
* simplifying and adding instructions for interpolation and
|
||||
* framebuffer writes.
|
||||
*/
|
||||
struct {
|
||||
GLfloat v[4];
|
||||
unsigned nr;
|
||||
} immediate[BRW_WM_MAX_CONST+3];
|
||||
GLuint nr_immediates;
|
||||
|
||||
struct brw_fp_instruction fp_instructions[BRW_WM_MAX_INSN];
|
||||
GLuint nr_fp_insns;
|
||||
GLuint fp_temp;
|
||||
GLuint fp_interp_emitted;
|
||||
GLuint fp_fragcolor_emitted;
|
||||
GLuint fp_first_internal_temp;
|
||||
|
||||
struct brw_fp_src fp_pixel_xy;
|
||||
struct brw_fp_src fp_delta_xy;
|
||||
struct brw_fp_src fp_pixel_w;
|
||||
|
||||
|
||||
/* Subsequent passes using SSA representation:
|
||||
*/
|
||||
struct brw_wm_value vreg[BRW_WM_MAX_VREG];
|
||||
GLuint nr_vreg;
|
||||
|
||||
struct brw_wm_value creg[BRW_WM_MAX_PARAM];
|
||||
GLuint nr_creg;
|
||||
|
||||
struct {
|
||||
struct brw_wm_value depth[4]; /* includes r0/r1 */
|
||||
struct brw_wm_value input_interp[PIPE_MAX_SHADER_INPUTS];
|
||||
} payload;
|
||||
|
||||
|
||||
const struct brw_wm_ref *pass0_fp_reg[BRW_FILE_PAYLOAD+1][256][4];
|
||||
|
||||
struct brw_wm_ref undef_ref;
|
||||
struct brw_wm_value undef_value;
|
||||
|
||||
struct brw_wm_ref refs[BRW_WM_MAX_REF];
|
||||
GLuint nr_refs;
|
||||
|
||||
struct brw_wm_instruction instruction[BRW_WM_MAX_INSN];
|
||||
GLuint nr_insns;
|
||||
|
||||
struct brw_wm_grf pass2_grf[BRW_WM_MAX_GRF/2];
|
||||
|
||||
GLuint grf_limit;
|
||||
GLuint max_wm_grf;
|
||||
GLuint last_scratch;
|
||||
|
||||
GLuint cur_inst; /**< index of current instruction */
|
||||
|
||||
GLboolean out_of_regs; /**< ran out of GRF registers? */
|
||||
|
||||
/** Mapping from Mesa registers to hardware registers */
|
||||
struct {
|
||||
GLboolean inited;
|
||||
struct brw_reg reg;
|
||||
} wm_regs[BRW_FILE_PAYLOAD+1][256][4];
|
||||
|
||||
GLboolean used_grf[BRW_WM_MAX_GRF];
|
||||
GLuint first_free_grf;
|
||||
struct brw_reg stack;
|
||||
struct brw_reg emit_mask_reg;
|
||||
GLuint tmp_regs[BRW_WM_MAX_GRF];
|
||||
GLuint tmp_index;
|
||||
GLuint tmp_max;
|
||||
GLuint subroutines[BRW_WM_MAX_SUBROUTINE];
|
||||
GLuint dispatch_width;
|
||||
|
||||
/** we may need up to 3 constants per instruction (if use_const_buffer) */
|
||||
struct {
|
||||
GLint index;
|
||||
struct brw_reg reg;
|
||||
} current_const[3];
|
||||
|
||||
GLuint error;
|
||||
};
|
||||
|
||||
|
||||
GLuint brw_wm_nr_args( GLuint opcode );
|
||||
GLuint brw_wm_is_scalar_result( GLuint opcode );
|
||||
|
||||
int brw_wm_pass_fp( struct brw_wm_compile *c );
|
||||
void brw_wm_pass0( struct brw_wm_compile *c );
|
||||
void brw_wm_pass1( struct brw_wm_compile *c );
|
||||
void brw_wm_pass2( struct brw_wm_compile *c );
|
||||
void brw_wm_emit( struct brw_wm_compile *c );
|
||||
|
||||
void brw_wm_print_value( struct brw_wm_compile *c,
|
||||
struct brw_wm_value *value );
|
||||
|
||||
void brw_wm_print_ref( struct brw_wm_compile *c,
|
||||
struct brw_wm_ref *ref );
|
||||
|
||||
void brw_wm_print_insn( struct brw_wm_compile *c,
|
||||
struct brw_wm_instruction *inst );
|
||||
|
||||
void brw_wm_print_program( struct brw_wm_compile *c,
|
||||
const char *stage );
|
||||
|
||||
void brw_wm_print_fp_program( struct brw_wm_compile *c,
|
||||
const char *stage );
|
||||
|
||||
void brw_wm_lookup_iz( GLuint line_aa,
|
||||
GLuint lookup,
|
||||
GLboolean ps_uses_depth,
|
||||
struct brw_wm_prog_key *key );
|
||||
|
||||
void brw_wm_branching_shader_emit(struct brw_context *brw, struct brw_wm_compile *c);
|
||||
|
||||
void emit_ddxy(struct brw_compile *p,
|
||||
const struct brw_reg *dst,
|
||||
GLuint mask,
|
||||
GLboolean is_ddx,
|
||||
const struct brw_reg *arg0);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,165 @@
|
||||
/* XXX: Constant buffers disabled
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Create the constant buffer surface. Vertex/fragment shader constants will be
|
||||
* read from this buffer with Data Port Read instructions/messages.
|
||||
*/
|
||||
enum pipe_error
|
||||
brw_create_constant_surface( struct brw_context *brw,
|
||||
struct brw_surface_key *key,
|
||||
struct brw_winsys_buffer **bo_out )
|
||||
{
|
||||
const GLint w = key->width - 1;
|
||||
struct brw_winsys_buffer *bo;
|
||||
struct brw_winsys_reloc reloc[1];
|
||||
enum pipe_error ret;
|
||||
|
||||
/* Emit relocation to surface contents */
|
||||
make_reloc(&reloc[0],
|
||||
BRW_USAGE_SAMPLER,
|
||||
0,
|
||||
offsetof(struct brw_surface_state, ss1),
|
||||
key->bo);
|
||||
|
||||
|
||||
memset(&surf, 0, sizeof(surf));
|
||||
|
||||
surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
|
||||
surf.ss0.surface_type = BRW_SURFACE_BUFFER;
|
||||
surf.ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
|
||||
|
||||
surf.ss1.base_addr = 0; /* reloc */
|
||||
|
||||
surf.ss2.width = w & 0x7f; /* bits 6:0 of size or width */
|
||||
surf.ss2.height = (w >> 7) & 0x1fff; /* bits 19:7 of size or width */
|
||||
surf.ss3.depth = (w >> 20) & 0x7f; /* bits 26:20 of size or width */
|
||||
surf.ss3.pitch = (key->pitch * key->cpp) - 1; /* ignored?? */
|
||||
brw_set_surface_tiling(&surf, key->tiling); /* tiling now allowed */
|
||||
|
||||
ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
|
||||
key, sizeof(*key),
|
||||
reloc, Elements(reloc),
|
||||
&surf, sizeof(surf),
|
||||
NULL, NULL,
|
||||
&bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update the surface state for a WM constant buffer.
|
||||
* The constant buffer will be (re)allocated here if needed.
|
||||
*/
|
||||
static enum pipe_error
|
||||
brw_update_wm_constant_surface( struct brw_context *brw,
|
||||
GLuint surf)
|
||||
{
|
||||
struct brw_surface_key key;
|
||||
struct brw_fragment_shader *fp = brw->curr.fragment_shader;
|
||||
struct pipe_buffer *cbuf = brw->curr.fragment_constants;
|
||||
int pitch = cbuf->size / (4 * sizeof(float));
|
||||
enum pipe_error ret;
|
||||
|
||||
/* If we're in this state update atom, we need to update WM constants, so
|
||||
* free the old buffer and create a new one for the new contents.
|
||||
*/
|
||||
ret = brw_wm_update_constant_buffer(brw, &fp->const_buffer);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If there's no constant buffer, then no surface BO is needed to point at
|
||||
* it.
|
||||
*/
|
||||
if (cbuf == NULL) {
|
||||
bo_reference(&brw->wm.surf_bo[surf], NULL);
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
|
||||
key.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
|
||||
key.ss0.surface_type = BRW_SURFACE_BUFFER;
|
||||
key.ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
|
||||
|
||||
key.bo = brw_buffer(cbuf)->bo;
|
||||
|
||||
key.ss2.width = (pitch-1) & 0x7f; /* bits 6:0 of size or width */
|
||||
key.ss2.height = ((pitch-1) >> 7) & 0x1fff; /* bits 19:7 of size or width */
|
||||
key.ss3.depth = ((pitch-1) >> 20) & 0x7f; /* bits 26:20 of size or width */
|
||||
key.ss3.pitch = (pitch * 4 * sizeof(float)) - 1; /* ignored?? */
|
||||
brw_set_surface_tiling(&surf, key->tiling); /* tiling now allowed */
|
||||
|
||||
|
||||
/*
|
||||
printf("%s:\n", __FUNCTION__);
|
||||
printf(" width %d height %d depth %d cpp %d pitch %d\n",
|
||||
key.width, key.height, key.depth, key.cpp, key.pitch);
|
||||
*/
|
||||
|
||||
if (brw_search_cache(&brw->surface_cache,
|
||||
BRW_SS_SURFACE,
|
||||
&key, sizeof(key),
|
||||
&key.bo, 1,
|
||||
NULL,
|
||||
&brw->wm.surf_bo[surf]))
|
||||
return PIPE_OK;
|
||||
|
||||
ret = brw_create_constant_surface(brw, &key, &brw->wm.surf_bo[surf]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates surface / buffer for fragment shader constant buffer, if
|
||||
* one is required.
|
||||
*
|
||||
* This consumes the state updates for the constant buffer, and produces
|
||||
* BRW_NEW_WM_SURFACES to get picked up by brw_prepare_wm_surfaces for
|
||||
* inclusion in the binding table.
|
||||
*/
|
||||
static enum pipe_error prepare_wm_constant_surface(struct brw_context *brw )
|
||||
{
|
||||
struct brw_fragment_program *fp =
|
||||
(struct brw_fragment_program *) brw->fragment_program;
|
||||
GLuint surf = SURF_INDEX_FRAG_CONST_BUFFER;
|
||||
|
||||
ret = brw_wm_update_constant_buffer(brw,
|
||||
&fp->const_buffer);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If there's no constant buffer, then no surface BO is needed to point at
|
||||
* it.
|
||||
*/
|
||||
if (fp->const_buffer == 0) {
|
||||
if (brw->wm.surf_bo[surf] != NULL) {
|
||||
bo_reference(&brw->wm.surf_bo[surf], NULL);
|
||||
brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
|
||||
}
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
ret = brw_update_wm_constant_surface(ctx, surf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_wm_constant_surface = {
|
||||
.dirty = {
|
||||
.mesa = (_NEW_PROGRAM_CONSTANTS),
|
||||
.brw = (BRW_NEW_FRAGMENT_PROGRAM),
|
||||
.cache = 0
|
||||
},
|
||||
.prepare = prepare_wm_constant_surface,
|
||||
};
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "tgsi/tgsi_info.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_wm.h"
|
||||
|
||||
static void print_writemask( unsigned writemask )
|
||||
{
|
||||
if (writemask != BRW_WRITEMASK_XYZW)
|
||||
debug_printf(".%s%s%s%s",
|
||||
(writemask & BRW_WRITEMASK_X) ? "x" : "",
|
||||
(writemask & BRW_WRITEMASK_Y) ? "y" : "",
|
||||
(writemask & BRW_WRITEMASK_Z) ? "z" : "",
|
||||
(writemask & BRW_WRITEMASK_W) ? "w" : "");
|
||||
}
|
||||
|
||||
static void print_swizzle( unsigned swizzle )
|
||||
{
|
||||
char *swz = "xyzw";
|
||||
if (swizzle != BRW_SWIZZLE_XYZW)
|
||||
debug_printf(".%c%c%c%c",
|
||||
swz[BRW_GET_SWZ(swizzle, X)],
|
||||
swz[BRW_GET_SWZ(swizzle, Y)],
|
||||
swz[BRW_GET_SWZ(swizzle, Z)],
|
||||
swz[BRW_GET_SWZ(swizzle, W)]);
|
||||
}
|
||||
|
||||
static void print_opcode( unsigned opcode )
|
||||
{
|
||||
switch (opcode) {
|
||||
case WM_PIXELXY:
|
||||
debug_printf("PIXELXY");
|
||||
break;
|
||||
case WM_DELTAXY:
|
||||
debug_printf("DELTAXY");
|
||||
break;
|
||||
case WM_PIXELW:
|
||||
debug_printf("PIXELW");
|
||||
break;
|
||||
case WM_WPOSXY:
|
||||
debug_printf("WPOSXY");
|
||||
break;
|
||||
case WM_PINTERP:
|
||||
debug_printf("PINTERP");
|
||||
break;
|
||||
case WM_LINTERP:
|
||||
debug_printf("LINTERP");
|
||||
break;
|
||||
case WM_CINTERP:
|
||||
debug_printf("CINTERP");
|
||||
break;
|
||||
case WM_FB_WRITE:
|
||||
debug_printf("FB_WRITE");
|
||||
break;
|
||||
case WM_FRONTFACING:
|
||||
debug_printf("FRONTFACING");
|
||||
break;
|
||||
default:
|
||||
debug_printf("%s", tgsi_get_opcode_info(opcode)->mnemonic);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void brw_wm_print_value( struct brw_wm_compile *c,
|
||||
struct brw_wm_value *value )
|
||||
{
|
||||
assert(value);
|
||||
if (c->state >= PASS2_DONE)
|
||||
brw_print_reg(value->hw_reg);
|
||||
else if( value == &c->undef_value )
|
||||
debug_printf("undef");
|
||||
else if( value - c->vreg >= 0 &&
|
||||
value - c->vreg < BRW_WM_MAX_VREG)
|
||||
debug_printf("r%d", value - c->vreg);
|
||||
else if (value - c->creg >= 0 &&
|
||||
value - c->creg < BRW_WM_MAX_PARAM)
|
||||
debug_printf("c%d", value - c->creg);
|
||||
else if (value - c->payload.input_interp >= 0 &&
|
||||
value - c->payload.input_interp < PIPE_MAX_SHADER_INPUTS)
|
||||
debug_printf("i%d", value - c->payload.input_interp);
|
||||
else if (value - c->payload.depth >= 0 &&
|
||||
value - c->payload.depth < PIPE_MAX_SHADER_INPUTS)
|
||||
debug_printf("d%d", value - c->payload.depth);
|
||||
else
|
||||
debug_printf("?");
|
||||
}
|
||||
|
||||
void brw_wm_print_ref( struct brw_wm_compile *c,
|
||||
struct brw_wm_ref *ref )
|
||||
{
|
||||
struct brw_reg hw_reg = ref->hw_reg;
|
||||
|
||||
if (ref->unspill_reg)
|
||||
debug_printf("UNSPILL(%x)/", ref->value->spill_slot);
|
||||
|
||||
if (c->state >= PASS2_DONE)
|
||||
brw_print_reg(ref->hw_reg);
|
||||
else {
|
||||
debug_printf("%s", hw_reg.negate ? "-" : "");
|
||||
debug_printf("%s", hw_reg.abs ? "abs/" : "");
|
||||
brw_wm_print_value(c, ref->value);
|
||||
if ((hw_reg.nr&1) || hw_reg.subnr) {
|
||||
debug_printf("->%d.%d", (hw_reg.nr&1), hw_reg.subnr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void brw_wm_print_insn( struct brw_wm_compile *c,
|
||||
struct brw_wm_instruction *inst )
|
||||
{
|
||||
GLuint i, arg;
|
||||
GLuint nr_args = brw_wm_nr_args(inst->opcode);
|
||||
|
||||
debug_printf("[");
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (inst->dst[i]) {
|
||||
brw_wm_print_value(c, inst->dst[i]);
|
||||
if (inst->dst[i]->spill_slot)
|
||||
debug_printf("/SPILL(%x)",inst->dst[i]->spill_slot);
|
||||
}
|
||||
else
|
||||
debug_printf("#");
|
||||
if (i < 3)
|
||||
debug_printf(",");
|
||||
}
|
||||
debug_printf("]");
|
||||
print_writemask(inst->writemask);
|
||||
|
||||
debug_printf(" = ");
|
||||
print_opcode(inst->opcode);
|
||||
|
||||
if (inst->saturate)
|
||||
debug_printf("_SAT");
|
||||
|
||||
for (arg = 0; arg < nr_args; arg++) {
|
||||
|
||||
debug_printf(" [");
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (inst->src[arg][i]) {
|
||||
brw_wm_print_ref(c, inst->src[arg][i]);
|
||||
}
|
||||
else
|
||||
debug_printf("%%");
|
||||
|
||||
if (i < 3)
|
||||
debug_printf(",");
|
||||
else
|
||||
debug_printf("]");
|
||||
}
|
||||
}
|
||||
debug_printf("\n");
|
||||
}
|
||||
|
||||
void brw_wm_print_program( struct brw_wm_compile *c,
|
||||
const char *stage )
|
||||
{
|
||||
GLuint insn;
|
||||
|
||||
debug_printf("%s:\n", stage);
|
||||
for (insn = 0; insn < c->nr_insns; insn++)
|
||||
brw_wm_print_insn(c, &c->instruction[insn]);
|
||||
debug_printf("\n");
|
||||
}
|
||||
|
||||
static const char *file_strings[TGSI_FILE_COUNT+1] = {
|
||||
"NULL",
|
||||
"CONST",
|
||||
"IN",
|
||||
"OUT",
|
||||
"TEMP",
|
||||
"SAMPLER",
|
||||
"ADDR",
|
||||
"IMM",
|
||||
"LOOP",
|
||||
"PAYLOAD"
|
||||
};
|
||||
|
||||
static void brw_wm_print_fp_insn( struct brw_wm_compile *c,
|
||||
struct brw_fp_instruction *inst )
|
||||
{
|
||||
GLuint i;
|
||||
GLuint nr_args = brw_wm_nr_args(inst->opcode);
|
||||
|
||||
print_opcode(inst->opcode);
|
||||
if (inst->dst.saturate)
|
||||
debug_printf("_SAT");
|
||||
debug_printf(" ");
|
||||
|
||||
if (inst->dst.indirect)
|
||||
debug_printf("[");
|
||||
|
||||
debug_printf("%s[%d]",
|
||||
file_strings[inst->dst.file],
|
||||
inst->dst.index );
|
||||
print_writemask(inst->dst.writemask);
|
||||
|
||||
if (inst->dst.indirect)
|
||||
debug_printf("]");
|
||||
|
||||
debug_printf(nr_args ? ", " : "\n");
|
||||
|
||||
for (i = 0; i < nr_args; i++) {
|
||||
debug_printf("%s%s%s[%d]%s",
|
||||
inst->src[i].negate ? "-" : "",
|
||||
inst->src[i].abs ? "ABS(" : "",
|
||||
file_strings[inst->src[i].file],
|
||||
inst->src[i].index,
|
||||
inst->src[i].abs ? ")" : "");
|
||||
print_swizzle(inst->src[i].swizzle);
|
||||
debug_printf("%s", i == nr_args - 1 ? "\n" : ", ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void brw_wm_print_fp_program( struct brw_wm_compile *c,
|
||||
const char *stage )
|
||||
{
|
||||
GLuint insn;
|
||||
|
||||
debug_printf("%s:\n", stage);
|
||||
for (insn = 0; insn < c->nr_fp_insns; insn++)
|
||||
brw_wm_print_fp_insn(c, &c->fp_instructions[insn]);
|
||||
debug_printf("\n");
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "brw_wm.h"
|
||||
|
||||
|
||||
#undef P /* prompted depth */
|
||||
#undef C /* computed */
|
||||
#undef N /* non-promoted? */
|
||||
|
||||
#define P 0
|
||||
#define C 1
|
||||
#define N 2
|
||||
|
||||
const struct {
|
||||
GLuint mode:2;
|
||||
GLuint sd_present:1;
|
||||
GLuint sd_to_rt:1;
|
||||
GLuint dd_present:1;
|
||||
GLuint ds_present:1;
|
||||
} wm_iz_table[IZ_BIT_MAX] =
|
||||
{
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ N, 1, 1, 0, 0 },
|
||||
{ N, 0, 1, 0, 0 },
|
||||
{ N, 0, 1, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ C, 0, 1, 1, 0 },
|
||||
{ C, 0, 1, 1, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ N, 1, 1, 0, 0 },
|
||||
{ C, 0, 1, 1, 0 },
|
||||
{ C, 0, 1, 1, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ N, 1, 1, 0, 0 },
|
||||
{ N, 0, 1, 0, 0 },
|
||||
{ N, 0, 1, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ C, 0, 1, 1, 0 },
|
||||
{ C, 0, 1, 1, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ N, 1, 1, 0, 0 },
|
||||
{ C, 0, 1, 1, 0 },
|
||||
{ C, 0, 1, 1, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ N, 1, 1, 0, 1 },
|
||||
{ N, 0, 1, 0, 1 },
|
||||
{ N, 0, 1, 0, 1 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ C, 0, 1, 1, 1 },
|
||||
{ C, 0, 1, 1, 1 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ N, 1, 1, 0, 1 },
|
||||
{ C, 0, 1, 1, 1 },
|
||||
{ C, 0, 1, 1, 1 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ C, 0, 0, 0, 1 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ C, 0, 1, 0, 1 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ C, 1, 1, 0, 1 },
|
||||
{ C, 0, 1, 0, 1 },
|
||||
{ C, 0, 1, 0, 1 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ C, 1, 1, 1, 1 },
|
||||
{ C, 0, 1, 1, 1 },
|
||||
{ C, 0, 1, 1, 1 },
|
||||
{ P, 0, 0, 0, 0 },
|
||||
{ C, 1, 1, 1, 1 },
|
||||
{ C, 0, 1, 1, 1 },
|
||||
{ C, 0, 1, 1, 1 }
|
||||
};
|
||||
|
||||
/**
|
||||
* \param line_aa AA_NEVER, AA_ALWAYS or AA_SOMETIMES
|
||||
* \param lookup bitmask of IZ_* flags
|
||||
*/
|
||||
void brw_wm_lookup_iz( GLuint line_aa,
|
||||
GLuint lookup,
|
||||
GLboolean ps_uses_depth,
|
||||
struct brw_wm_prog_key *key )
|
||||
{
|
||||
GLuint reg = 2;
|
||||
|
||||
assert (lookup < IZ_BIT_MAX);
|
||||
|
||||
if (lookup & IZ_PS_COMPUTES_DEPTH_BIT)
|
||||
key->computes_depth = 1;
|
||||
|
||||
if (wm_iz_table[lookup].sd_present || ps_uses_depth) {
|
||||
key->source_depth_reg = reg;
|
||||
reg += 2;
|
||||
}
|
||||
|
||||
if (wm_iz_table[lookup].sd_to_rt)
|
||||
key->source_depth_to_render_target = 1;
|
||||
|
||||
if (wm_iz_table[lookup].ds_present || line_aa != AA_NEVER) {
|
||||
key->aa_dest_stencil_reg = reg;
|
||||
key->runtime_check_aads_emit = (!wm_iz_table[lookup].ds_present &&
|
||||
line_aa == AA_SOMETIMES);
|
||||
reg++;
|
||||
}
|
||||
|
||||
if (wm_iz_table[lookup].dd_present) {
|
||||
key->dest_depth_reg = reg;
|
||||
reg+=2;
|
||||
}
|
||||
|
||||
key->nr_depth_regs = (reg+1)/2;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "brw_debug.h"
|
||||
#include "brw_wm.h"
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*/
|
||||
|
||||
static struct brw_wm_ref *get_ref( struct brw_wm_compile *c )
|
||||
{
|
||||
assert(c->nr_refs < BRW_WM_MAX_REF);
|
||||
return &c->refs[c->nr_refs++];
|
||||
}
|
||||
|
||||
static struct brw_wm_value *get_value( struct brw_wm_compile *c)
|
||||
{
|
||||
assert(c->nr_refs < BRW_WM_MAX_VREG);
|
||||
return &c->vreg[c->nr_vreg++];
|
||||
}
|
||||
|
||||
/** return pointer to a newly allocated instruction */
|
||||
static struct brw_wm_instruction *get_instruction( struct brw_wm_compile *c )
|
||||
{
|
||||
assert(c->nr_insns < BRW_WM_MAX_INSN);
|
||||
return &c->instruction[c->nr_insns++];
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*/
|
||||
|
||||
/** Init the "undef" register */
|
||||
static void pass0_init_undef( struct brw_wm_compile *c)
|
||||
{
|
||||
struct brw_wm_ref *ref = &c->undef_ref;
|
||||
ref->value = &c->undef_value;
|
||||
ref->hw_reg = brw_vec8_grf(0, 0);
|
||||
ref->insn = 0;
|
||||
ref->prevuse = NULL;
|
||||
}
|
||||
|
||||
/** Set a FP register to a value */
|
||||
static void pass0_set_fpreg_value( struct brw_wm_compile *c,
|
||||
GLuint file,
|
||||
GLuint idx,
|
||||
GLuint component,
|
||||
struct brw_wm_value *value )
|
||||
{
|
||||
struct brw_wm_ref *ref = get_ref(c);
|
||||
ref->value = value;
|
||||
ref->hw_reg = brw_vec8_grf(0, 0);
|
||||
ref->insn = 0;
|
||||
ref->prevuse = NULL;
|
||||
c->pass0_fp_reg[file][idx][component] = ref;
|
||||
}
|
||||
|
||||
/** Set a FP register to a ref */
|
||||
static void pass0_set_fpreg_ref( struct brw_wm_compile *c,
|
||||
GLuint file,
|
||||
GLuint idx,
|
||||
GLuint component,
|
||||
const struct brw_wm_ref *src_ref )
|
||||
{
|
||||
c->pass0_fp_reg[file][idx][component] = src_ref;
|
||||
}
|
||||
|
||||
static const struct brw_wm_ref *get_param_ref( struct brw_wm_compile *c,
|
||||
unsigned idx,
|
||||
unsigned component)
|
||||
{
|
||||
GLuint i = idx * 4 + component;
|
||||
|
||||
if (i >= BRW_WM_MAX_PARAM) {
|
||||
debug_printf("%s: out of params\n", __FUNCTION__);
|
||||
c->prog_data.error = 1;
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
struct brw_wm_ref *ref = get_ref(c);
|
||||
|
||||
c->nr_creg = MAX2(c->nr_creg, (i+16)/16);
|
||||
|
||||
/* Push the offsets into hw_reg. These will be added to the
|
||||
* real register numbers once one is allocated in pass2.
|
||||
*/
|
||||
ref->hw_reg = brw_vec1_grf((i&8)?1:0, i%8);
|
||||
ref->value = &c->creg[i/16];
|
||||
ref->insn = 0;
|
||||
ref->prevuse = NULL;
|
||||
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Lookup our internal registers
|
||||
*/
|
||||
static const struct brw_wm_ref *pass0_get_reg( struct brw_wm_compile *c,
|
||||
GLuint file,
|
||||
GLuint idx,
|
||||
GLuint component )
|
||||
{
|
||||
const struct brw_wm_ref *ref = c->pass0_fp_reg[file][idx][component];
|
||||
|
||||
if (!ref) {
|
||||
switch (file) {
|
||||
case TGSI_FILE_INPUT:
|
||||
case TGSI_FILE_TEMPORARY:
|
||||
case TGSI_FILE_OUTPUT:
|
||||
case BRW_FILE_PAYLOAD:
|
||||
/* should already be done?? */
|
||||
break;
|
||||
|
||||
case TGSI_FILE_CONSTANT:
|
||||
ref = get_param_ref(c,
|
||||
c->fp->info.immediate_count + idx,
|
||||
component);
|
||||
break;
|
||||
|
||||
case TGSI_FILE_IMMEDIATE:
|
||||
ref = get_param_ref(c,
|
||||
idx,
|
||||
component);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
c->pass0_fp_reg[file][idx][component] = ref;
|
||||
}
|
||||
|
||||
if (!ref)
|
||||
ref = &c->undef_ref;
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Straight translation to internal instruction format
|
||||
*/
|
||||
|
||||
static void pass0_set_dst( struct brw_wm_compile *c,
|
||||
struct brw_wm_instruction *out,
|
||||
const struct brw_fp_instruction *inst,
|
||||
GLuint writemask )
|
||||
{
|
||||
const struct brw_fp_dst dst = inst->dst;
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (writemask & (1<<i)) {
|
||||
out->dst[i] = get_value(c);
|
||||
pass0_set_fpreg_value(c, dst.file, dst.index, i, out->dst[i]);
|
||||
}
|
||||
}
|
||||
|
||||
out->writemask = writemask;
|
||||
}
|
||||
|
||||
|
||||
static const struct brw_wm_ref *get_fp_src_reg_ref( struct brw_wm_compile *c,
|
||||
struct brw_fp_src src,
|
||||
GLuint i )
|
||||
{
|
||||
return pass0_get_reg(c, src.file, src.index, BRW_GET_SWZ(src.swizzle,i));
|
||||
}
|
||||
|
||||
|
||||
static struct brw_wm_ref *get_new_ref( struct brw_wm_compile *c,
|
||||
struct brw_fp_src src,
|
||||
GLuint i,
|
||||
struct brw_wm_instruction *insn)
|
||||
{
|
||||
const struct brw_wm_ref *ref = get_fp_src_reg_ref(c, src, i);
|
||||
struct brw_wm_ref *newref = get_ref(c);
|
||||
|
||||
newref->value = ref->value;
|
||||
newref->hw_reg = ref->hw_reg;
|
||||
|
||||
if (insn) {
|
||||
newref->insn = insn - c->instruction;
|
||||
newref->prevuse = newref->value->lastuse;
|
||||
newref->value->lastuse = newref;
|
||||
}
|
||||
|
||||
if (src.negate)
|
||||
newref->hw_reg.negate ^= 1;
|
||||
|
||||
if (src.abs) {
|
||||
newref->hw_reg.negate = 0;
|
||||
newref->hw_reg.abs = 1;
|
||||
}
|
||||
|
||||
return newref;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
translate_insn(struct brw_wm_compile *c,
|
||||
const struct brw_fp_instruction *inst)
|
||||
{
|
||||
struct brw_wm_instruction *out = get_instruction(c);
|
||||
GLuint writemask = inst->dst.writemask;
|
||||
GLuint nr_args = brw_wm_nr_args(inst->opcode);
|
||||
GLuint i, j;
|
||||
|
||||
/* Copy some data out of the instruction
|
||||
*/
|
||||
out->opcode = inst->opcode;
|
||||
out->saturate = inst->dst.saturate;
|
||||
out->tex_unit = inst->tex_unit;
|
||||
out->target = inst->target;
|
||||
|
||||
/* Nasty hack:
|
||||
*/
|
||||
out->eot = (inst->opcode == WM_FB_WRITE &&
|
||||
inst->tex_unit != 0);
|
||||
|
||||
|
||||
/* Args:
|
||||
*/
|
||||
for (i = 0; i < nr_args; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
out->src[i][j] = get_new_ref(c, inst->src[i], j, out);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dst:
|
||||
*/
|
||||
pass0_set_dst(c, out, inst, writemask);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Optimize moves and swizzles away:
|
||||
*/
|
||||
static void pass0_precalc_mov( struct brw_wm_compile *c,
|
||||
const struct brw_fp_instruction *inst )
|
||||
{
|
||||
const struct brw_fp_dst dst = inst->dst;
|
||||
GLuint writemask = dst.writemask;
|
||||
struct brw_wm_ref *refs[4];
|
||||
GLuint i;
|
||||
|
||||
/* Get the effect of a MOV by manipulating our register table:
|
||||
* First get all refs, then assign refs. This ensures that "in-place"
|
||||
* swizzles such as:
|
||||
* MOV t, t.xxyx
|
||||
* are handled correctly. Previously, these two steps were done in
|
||||
* one loop and the above case was incorrectly handled.
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
refs[i] = get_new_ref(c, inst->src[0], i, NULL);
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (writemask & (1 << i)) {
|
||||
pass0_set_fpreg_ref( c, dst.file, dst.index, i, refs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Initialize payload "registers".
|
||||
*/
|
||||
static void pass0_init_payload( struct brw_wm_compile *c )
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
GLuint j = i >= c->key.nr_depth_regs ? 0 : i;
|
||||
pass0_set_fpreg_value( c, BRW_FILE_PAYLOAD, PAYLOAD_DEPTH, i,
|
||||
&c->payload.depth[j] );
|
||||
}
|
||||
|
||||
for (i = 0; i < c->key.nr_inputs; i++)
|
||||
pass0_set_fpreg_value( c, BRW_FILE_PAYLOAD, i, 0,
|
||||
&c->payload.input_interp[i] );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PASS 0
|
||||
*
|
||||
* Work forwards to give each calculated value a unique number. Where
|
||||
* an instruction produces duplicate values (eg DP3), all are given
|
||||
* the same number.
|
||||
*
|
||||
* Translate away swizzling and eliminate non-saturating moves.
|
||||
*
|
||||
* Translate instructions from our fp_instruction structs to our
|
||||
* internal brw_wm_instruction representation.
|
||||
*/
|
||||
void brw_wm_pass0( struct brw_wm_compile *c )
|
||||
{
|
||||
GLuint insn;
|
||||
|
||||
c->nr_vreg = 0;
|
||||
c->nr_insns = 0;
|
||||
|
||||
pass0_init_undef(c);
|
||||
pass0_init_payload(c);
|
||||
|
||||
for (insn = 0; insn < c->nr_fp_insns; insn++) {
|
||||
const struct brw_fp_instruction *inst = &c->fp_instructions[insn];
|
||||
|
||||
/* Optimize away moves, otherwise emit translated instruction:
|
||||
*/
|
||||
switch (inst->opcode) {
|
||||
case TGSI_OPCODE_MOV:
|
||||
if (!inst->dst.saturate) {
|
||||
pass0_precalc_mov(c, inst);
|
||||
}
|
||||
else {
|
||||
translate_insn(c, inst);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
translate_insn(c, inst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (BRW_DEBUG & DEBUG_WM) {
|
||||
brw_wm_print_program(c, "pass0");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "brw_wm.h"
|
||||
#include "brw_debug.h"
|
||||
|
||||
|
||||
static GLuint get_tracked_mask(struct brw_wm_compile *c,
|
||||
struct brw_wm_instruction *inst)
|
||||
{
|
||||
GLuint i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (inst->writemask & (1<<i)) {
|
||||
if (!inst->dst[i]->contributes_to_output) {
|
||||
inst->writemask &= ~(1<<i);
|
||||
inst->dst[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return inst->writemask;
|
||||
}
|
||||
|
||||
/* Remove a reference from a value's usage chain.
|
||||
*/
|
||||
static void unlink_ref(struct brw_wm_ref *ref)
|
||||
{
|
||||
struct brw_wm_value *value = ref->value;
|
||||
|
||||
if (ref == value->lastuse) {
|
||||
value->lastuse = ref->prevuse;
|
||||
}
|
||||
else {
|
||||
struct brw_wm_ref *i = value->lastuse;
|
||||
while (i->prevuse != ref) i = i->prevuse;
|
||||
i->prevuse = ref->prevuse;
|
||||
}
|
||||
}
|
||||
|
||||
static void track_arg(struct brw_wm_compile *c,
|
||||
struct brw_wm_instruction *inst,
|
||||
GLuint arg,
|
||||
GLuint readmask)
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
struct brw_wm_ref *ref = inst->src[arg][i];
|
||||
if (ref) {
|
||||
if (readmask & (1<<i)) {
|
||||
ref->value->contributes_to_output = 1;
|
||||
}
|
||||
else {
|
||||
unlink_ref(ref);
|
||||
inst->src[arg][i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GLuint get_texcoord_mask( GLuint tex_idx )
|
||||
{
|
||||
switch (tex_idx) {
|
||||
case TGSI_TEXTURE_1D:
|
||||
return BRW_WRITEMASK_X;
|
||||
case TGSI_TEXTURE_2D:
|
||||
case TGSI_TEXTURE_RECT:
|
||||
return BRW_WRITEMASK_XY;
|
||||
case TGSI_TEXTURE_3D:
|
||||
return BRW_WRITEMASK_XYZ;
|
||||
case TGSI_TEXTURE_CUBE:
|
||||
return BRW_WRITEMASK_XYZ;
|
||||
|
||||
case TGSI_TEXTURE_SHADOW1D:
|
||||
return BRW_WRITEMASK_XZ;
|
||||
case TGSI_TEXTURE_SHADOW2D:
|
||||
case TGSI_TEXTURE_SHADOWRECT:
|
||||
return BRW_WRITEMASK_XYZ;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Step two: Basically this is dead code elimination.
|
||||
*
|
||||
* Iterate backwards over instructions, noting which values
|
||||
* contribute to the final result. Adjust writemasks to only
|
||||
* calculate these values.
|
||||
*/
|
||||
void brw_wm_pass1( struct brw_wm_compile *c )
|
||||
{
|
||||
GLint insn;
|
||||
|
||||
for (insn = c->nr_insns-1; insn >= 0; insn--) {
|
||||
struct brw_wm_instruction *inst = &c->instruction[insn];
|
||||
GLuint writemask;
|
||||
GLuint read0, read1, read2;
|
||||
|
||||
if (inst->opcode == TGSI_OPCODE_KIL) {
|
||||
track_arg(c, inst, 0, BRW_WRITEMASK_XYZW); /* All args contribute to final */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inst->opcode == WM_FB_WRITE) {
|
||||
track_arg(c, inst, 0, BRW_WRITEMASK_XYZW);
|
||||
track_arg(c, inst, 1, BRW_WRITEMASK_XYZW);
|
||||
if (c->key.source_depth_to_render_target &&
|
||||
c->key.computes_depth)
|
||||
track_arg(c, inst, 2, BRW_WRITEMASK_Z);
|
||||
else
|
||||
track_arg(c, inst, 2, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Lookup all the registers which were written by this
|
||||
* instruction and get a mask of those that contribute to the output:
|
||||
*/
|
||||
writemask = get_tracked_mask(c, inst);
|
||||
if (!writemask) {
|
||||
GLuint arg;
|
||||
for (arg = 0; arg < 3; arg++)
|
||||
track_arg(c, inst, arg, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
read0 = 0;
|
||||
read1 = 0;
|
||||
read2 = 0;
|
||||
|
||||
/* Mark all inputs which contribute to the marked outputs:
|
||||
*/
|
||||
switch (inst->opcode) {
|
||||
case TGSI_OPCODE_ABS:
|
||||
case TGSI_OPCODE_FLR:
|
||||
case TGSI_OPCODE_FRC:
|
||||
case TGSI_OPCODE_MOV:
|
||||
case TGSI_OPCODE_TRUNC:
|
||||
read0 = writemask;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_SUB:
|
||||
case TGSI_OPCODE_SLT:
|
||||
case TGSI_OPCODE_SLE:
|
||||
case TGSI_OPCODE_SGE:
|
||||
case TGSI_OPCODE_SGT:
|
||||
case TGSI_OPCODE_SEQ:
|
||||
case TGSI_OPCODE_SNE:
|
||||
case TGSI_OPCODE_ADD:
|
||||
case TGSI_OPCODE_MAX:
|
||||
case TGSI_OPCODE_MIN:
|
||||
case TGSI_OPCODE_MUL:
|
||||
read0 = writemask;
|
||||
read1 = writemask;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_DDX:
|
||||
case TGSI_OPCODE_DDY:
|
||||
read0 = writemask;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_MAD:
|
||||
case TGSI_OPCODE_CMP:
|
||||
case TGSI_OPCODE_LRP:
|
||||
read0 = writemask;
|
||||
read1 = writemask;
|
||||
read2 = writemask;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_XPD:
|
||||
if (writemask & BRW_WRITEMASK_X) read0 |= BRW_WRITEMASK_YZ;
|
||||
if (writemask & BRW_WRITEMASK_Y) read0 |= BRW_WRITEMASK_XZ;
|
||||
if (writemask & BRW_WRITEMASK_Z) read0 |= BRW_WRITEMASK_XY;
|
||||
read1 = read0;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_COS:
|
||||
case TGSI_OPCODE_EX2:
|
||||
case TGSI_OPCODE_LG2:
|
||||
case TGSI_OPCODE_RCP:
|
||||
case TGSI_OPCODE_RSQ:
|
||||
case TGSI_OPCODE_SIN:
|
||||
case TGSI_OPCODE_SCS:
|
||||
case WM_CINTERP:
|
||||
case WM_PIXELXY:
|
||||
read0 = BRW_WRITEMASK_X;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_POW:
|
||||
read0 = BRW_WRITEMASK_X;
|
||||
read1 = BRW_WRITEMASK_X;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_TEX:
|
||||
case TGSI_OPCODE_TXP:
|
||||
read0 = get_texcoord_mask(inst->target);
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_TXB:
|
||||
read0 = get_texcoord_mask(inst->target) | BRW_WRITEMASK_W;
|
||||
break;
|
||||
|
||||
case WM_WPOSXY:
|
||||
read0 = writemask & BRW_WRITEMASK_XY;
|
||||
break;
|
||||
|
||||
case WM_DELTAXY:
|
||||
read0 = writemask & BRW_WRITEMASK_XY;
|
||||
read1 = BRW_WRITEMASK_X;
|
||||
break;
|
||||
|
||||
case WM_PIXELW:
|
||||
read0 = BRW_WRITEMASK_X;
|
||||
read1 = BRW_WRITEMASK_XY;
|
||||
break;
|
||||
|
||||
case WM_LINTERP:
|
||||
read0 = BRW_WRITEMASK_X;
|
||||
read1 = BRW_WRITEMASK_XY;
|
||||
break;
|
||||
|
||||
case WM_PINTERP:
|
||||
read0 = BRW_WRITEMASK_X; /* interpolant */
|
||||
read1 = BRW_WRITEMASK_XY; /* deltas */
|
||||
read2 = BRW_WRITEMASK_W; /* pixel w */
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_DP3:
|
||||
read0 = BRW_WRITEMASK_XYZ;
|
||||
read1 = BRW_WRITEMASK_XYZ;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_DPH:
|
||||
read0 = BRW_WRITEMASK_XYZ;
|
||||
read1 = BRW_WRITEMASK_XYZW;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_DP4:
|
||||
read0 = BRW_WRITEMASK_XYZW;
|
||||
read1 = BRW_WRITEMASK_XYZW;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_LIT:
|
||||
read0 = BRW_WRITEMASK_XYW;
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_DST:
|
||||
case WM_FRONTFACING:
|
||||
case TGSI_OPCODE_KILP:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
track_arg(c, inst, 0, read0);
|
||||
track_arg(c, inst, 1, read1);
|
||||
track_arg(c, inst, 2, read2);
|
||||
}
|
||||
|
||||
if (BRW_DEBUG & DEBUG_WM) {
|
||||
brw_wm_print_program(c, "pass1");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "brw_debug.h"
|
||||
#include "brw_wm.h"
|
||||
|
||||
|
||||
/* Use these to force spilling so that that functionality can be
|
||||
* tested with known-good examples rather than having to construct new
|
||||
* tests.
|
||||
*/
|
||||
#define TEST_PAYLOAD_SPILLS 0
|
||||
#define TEST_DST_SPILLS 0
|
||||
|
||||
static void spill_value(struct brw_wm_compile *c,
|
||||
struct brw_wm_value *value);
|
||||
|
||||
static void prealloc_reg(struct brw_wm_compile *c,
|
||||
struct brw_wm_value *value,
|
||||
GLuint reg)
|
||||
{
|
||||
if (value->lastuse) {
|
||||
/* Set nextuse to zero, it will be corrected by
|
||||
* update_register_usage().
|
||||
*/
|
||||
c->pass2_grf[reg].value = value;
|
||||
c->pass2_grf[reg].nextuse = 0;
|
||||
|
||||
value->resident = &c->pass2_grf[reg];
|
||||
value->hw_reg = brw_vec8_grf(reg*2, 0);
|
||||
|
||||
if (TEST_PAYLOAD_SPILLS)
|
||||
spill_value(c, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Initialize all the register values. Do the initial setup
|
||||
* calculations for interpolants.
|
||||
*/
|
||||
static void init_registers( struct brw_wm_compile *c )
|
||||
{
|
||||
GLuint reg = 0;
|
||||
GLuint j;
|
||||
|
||||
for (j = 0; j < c->grf_limit; j++)
|
||||
c->pass2_grf[j].nextuse = BRW_WM_MAX_INSN;
|
||||
|
||||
/* Pre-allocate incoming payload regs:
|
||||
*/
|
||||
for (j = 0; j < c->key.nr_depth_regs; j++)
|
||||
prealloc_reg(c, &c->payload.depth[j], reg++);
|
||||
|
||||
for (j = 0; j < c->nr_creg; j++)
|
||||
prealloc_reg(c, &c->creg[j], reg++);
|
||||
|
||||
reg++; /* XXX: skip over position output */
|
||||
|
||||
/* XXX: currently just hope the VS outputs line up with FS inputs:
|
||||
*/
|
||||
for (j = 0; j < c->key.nr_inputs; j++)
|
||||
prealloc_reg(c, &c->payload.input_interp[j], reg++);
|
||||
|
||||
c->prog_data.first_curbe_grf = c->key.nr_depth_regs * 2;
|
||||
c->prog_data.urb_read_length = (c->key.nr_inputs + 1) * 2;
|
||||
c->prog_data.curb_read_length = c->nr_creg * 2;
|
||||
|
||||
/* Note this allocation:
|
||||
*/
|
||||
c->max_wm_grf = reg * 2;
|
||||
}
|
||||
|
||||
|
||||
/* Update the nextuse value for each register in our file.
|
||||
*/
|
||||
static void update_register_usage(struct brw_wm_compile *c,
|
||||
GLuint thisinsn)
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
for (i = 1; i < c->grf_limit; i++) {
|
||||
struct brw_wm_grf *grf = &c->pass2_grf[i];
|
||||
|
||||
/* Only search those which can change:
|
||||
*/
|
||||
if (grf->nextuse < thisinsn) {
|
||||
const struct brw_wm_ref *ref = grf->value->lastuse;
|
||||
|
||||
/* Has last use of value been passed?
|
||||
*/
|
||||
if (ref->insn < thisinsn) {
|
||||
grf->value->resident = 0;
|
||||
grf->value = 0;
|
||||
grf->nextuse = BRW_WM_MAX_INSN;
|
||||
}
|
||||
else {
|
||||
/* Else loop through chain to update:
|
||||
*/
|
||||
while (ref->prevuse && ref->prevuse->insn >= thisinsn)
|
||||
ref = ref->prevuse;
|
||||
|
||||
grf->nextuse = ref->insn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void spill_value(struct brw_wm_compile *c,
|
||||
struct brw_wm_value *value)
|
||||
{
|
||||
/* Allocate a spill slot. Note that allocations start from 0x40 -
|
||||
* the first slot is reserved to mean "undef" in brw_wm_emit.c
|
||||
*/
|
||||
if (!value->spill_slot) {
|
||||
c->last_scratch += 0x40;
|
||||
value->spill_slot = c->last_scratch;
|
||||
}
|
||||
|
||||
/* The spill will be done in brw_wm_emit.c immediately after the
|
||||
* value is calculated, so we can just take this reg without any
|
||||
* further work.
|
||||
*/
|
||||
value->resident->value = NULL;
|
||||
value->resident->nextuse = BRW_WM_MAX_INSN;
|
||||
value->resident = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Search for contiguous region with the most distant nearest
|
||||
* member. Free regs count as very distant.
|
||||
*
|
||||
* TODO: implement spill-to-reg so that we can rearrange discontigous
|
||||
* free regs and then spill the oldest non-free regs in sequence.
|
||||
* This would mean inserting instructions in this pass.
|
||||
*/
|
||||
static GLuint search_contiguous_regs(struct brw_wm_compile *c,
|
||||
GLuint nr,
|
||||
GLuint thisinsn)
|
||||
{
|
||||
struct brw_wm_grf *grf = c->pass2_grf;
|
||||
GLuint furthest = 0;
|
||||
GLuint reg = 0;
|
||||
GLuint i, j;
|
||||
|
||||
/* Start search at 1: r0 is special and can't be used or spilled.
|
||||
*/
|
||||
for (i = 1; i < c->grf_limit && furthest < BRW_WM_MAX_INSN; i++) {
|
||||
GLuint group_nextuse = BRW_WM_MAX_INSN;
|
||||
|
||||
for (j = 0; j < nr; j++) {
|
||||
if (grf[i+j].nextuse < group_nextuse)
|
||||
group_nextuse = grf[i+j].nextuse;
|
||||
}
|
||||
|
||||
if (group_nextuse > furthest) {
|
||||
furthest = group_nextuse;
|
||||
reg = i;
|
||||
}
|
||||
}
|
||||
|
||||
assert(furthest != thisinsn);
|
||||
|
||||
/* Any non-empty regs will need to be spilled:
|
||||
*/
|
||||
for (j = 0; j < nr; j++)
|
||||
if (grf[reg+j].value)
|
||||
spill_value(c, grf[reg+j].value);
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
|
||||
static void alloc_contiguous_dest(struct brw_wm_compile *c,
|
||||
struct brw_wm_value *dst[],
|
||||
GLuint nr,
|
||||
GLuint thisinsn)
|
||||
{
|
||||
GLuint reg = search_contiguous_regs(c, nr, thisinsn);
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
if (!dst[i]) {
|
||||
/* Need to grab a dummy value in TEX case. Don't introduce
|
||||
* it into the tracking scheme.
|
||||
*/
|
||||
dst[i] = &c->vreg[c->nr_vreg++];
|
||||
}
|
||||
else {
|
||||
assert(!dst[i]->resident);
|
||||
assert(c->pass2_grf[reg+i].nextuse != thisinsn);
|
||||
|
||||
c->pass2_grf[reg+i].value = dst[i];
|
||||
c->pass2_grf[reg+i].nextuse = thisinsn;
|
||||
|
||||
dst[i]->resident = &c->pass2_grf[reg+i];
|
||||
}
|
||||
|
||||
dst[i]->hw_reg = brw_vec8_grf((reg+i)*2, 0);
|
||||
}
|
||||
|
||||
if ((reg+nr)*2 > c->max_wm_grf)
|
||||
c->max_wm_grf = (reg+nr) * 2;
|
||||
}
|
||||
|
||||
|
||||
static void load_args(struct brw_wm_compile *c,
|
||||
struct brw_wm_instruction *inst)
|
||||
{
|
||||
GLuint thisinsn = inst - c->instruction;
|
||||
GLuint i,j;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
struct brw_wm_ref *ref = inst->src[i][j];
|
||||
|
||||
if (ref) {
|
||||
if (!ref->value->resident) {
|
||||
/* Need to bring the value in from scratch space. The code for
|
||||
* this will be done in brw_wm_emit.c, here we just do the
|
||||
* register allocation and mark the ref as requiring a fill.
|
||||
*/
|
||||
GLuint reg = search_contiguous_regs(c, 1, thisinsn);
|
||||
|
||||
c->pass2_grf[reg].value = ref->value;
|
||||
c->pass2_grf[reg].nextuse = thisinsn;
|
||||
|
||||
ref->value->resident = &c->pass2_grf[reg];
|
||||
|
||||
/* Note that a fill is required:
|
||||
*/
|
||||
ref->unspill_reg = reg*2;
|
||||
}
|
||||
|
||||
/* Adjust the hw_reg to point at the value's current location:
|
||||
*/
|
||||
assert(ref->value == ref->value->resident->value);
|
||||
ref->hw_reg.nr += (ref->value->resident - c->pass2_grf) * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Step 3: Work forwards once again. Perform register allocations,
|
||||
* taking into account instructions like TEX which require contiguous
|
||||
* result registers. Where necessary spill registers to scratch space
|
||||
* and reload later.
|
||||
*/
|
||||
void brw_wm_pass2( struct brw_wm_compile *c )
|
||||
{
|
||||
GLuint insn;
|
||||
GLuint i;
|
||||
|
||||
init_registers(c);
|
||||
|
||||
for (insn = 0; insn < c->nr_insns; insn++) {
|
||||
struct brw_wm_instruction *inst = &c->instruction[insn];
|
||||
|
||||
/* Update registers' nextuse values:
|
||||
*/
|
||||
update_register_usage(c, insn);
|
||||
|
||||
/* May need to unspill some args.
|
||||
*/
|
||||
load_args(c, inst);
|
||||
|
||||
/* Allocate registers to hold results:
|
||||
*/
|
||||
switch (inst->opcode) {
|
||||
case TGSI_OPCODE_TEX:
|
||||
case TGSI_OPCODE_TXB:
|
||||
case TGSI_OPCODE_TXP:
|
||||
alloc_contiguous_dest(c, inst->dst, 4, insn);
|
||||
break;
|
||||
|
||||
default:
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (inst->writemask & (1<<i)) {
|
||||
assert(inst->dst[i]);
|
||||
alloc_contiguous_dest(c, &inst->dst[i], 1, insn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (TEST_DST_SPILLS && inst->opcode != WM_PIXELXY) {
|
||||
for (i = 0; i < 4; i++)
|
||||
if (inst->dst[i])
|
||||
spill_value(c, inst->dst[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (BRW_DEBUG & DEBUG_WM) {
|
||||
brw_wm_print_program(c, "pass2");
|
||||
}
|
||||
|
||||
c->state = PASS2_DONE;
|
||||
|
||||
if (BRW_DEBUG & DEBUG_WM) {
|
||||
brw_wm_print_program(c, "pass2/done");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_screen.h"
|
||||
|
||||
|
||||
/* Samplers aren't strictly wm state from the hardware's perspective,
|
||||
* but that is the only situation in which we use them in this driver.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static enum pipe_error
|
||||
upload_default_color( struct brw_context *brw,
|
||||
const GLfloat *color,
|
||||
struct brw_winsys_buffer **bo_out )
|
||||
{
|
||||
struct brw_sampler_default_color sdc;
|
||||
enum pipe_error ret;
|
||||
|
||||
COPY_4V(sdc.color, color);
|
||||
|
||||
ret = brw_cache_data( &brw->cache, BRW_SAMPLER_DEFAULT_COLOR, &sdc,
|
||||
NULL, 0, bo_out );
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
struct wm_sampler_key {
|
||||
int sampler_count;
|
||||
struct brw_sampler_state sampler[BRW_MAX_TEX_UNIT];
|
||||
};
|
||||
|
||||
|
||||
/** Sets up the cache key for sampler state for all texture units */
|
||||
static void
|
||||
brw_wm_sampler_populate_key(struct brw_context *brw,
|
||||
struct wm_sampler_key *key)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(key, 0, sizeof(*key));
|
||||
|
||||
key->sampler_count = MIN2(brw->curr.num_textures,
|
||||
brw->curr.num_samplers);
|
||||
|
||||
for (i = 0; i < key->sampler_count; i++) {
|
||||
const struct brw_texture *tex = brw_texture(brw->curr.texture[i]);
|
||||
const struct brw_sampler *sampler = brw->curr.sampler[i];
|
||||
struct brw_sampler_state *entry = &key->sampler[i];
|
||||
|
||||
entry->ss0 = sampler->ss0;
|
||||
entry->ss1 = sampler->ss1;
|
||||
entry->ss2.default_color_pointer = 0; /* reloc */
|
||||
entry->ss3 = sampler->ss3;
|
||||
|
||||
/* Cube-maps on 965 and later must use the same wrap mode for all 3
|
||||
* coordinate dimensions. Futher, only CUBE and CLAMP are valid.
|
||||
*/
|
||||
if (tex->base.target == PIPE_TEXTURE_CUBE) {
|
||||
if (FALSE &&
|
||||
(sampler->ss0.min_filter != BRW_MAPFILTER_NEAREST ||
|
||||
sampler->ss0.mag_filter != BRW_MAPFILTER_NEAREST)) {
|
||||
entry->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
|
||||
entry->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
|
||||
entry->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
|
||||
} else {
|
||||
entry->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
|
||||
entry->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
|
||||
entry->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
|
||||
}
|
||||
} else if (tex->base.target == PIPE_TEXTURE_1D) {
|
||||
/* There's a bug in 1D texture sampling - it actually pays
|
||||
* attention to the wrap_t value, though it should not.
|
||||
* Override the wrap_t value here to GL_REPEAT to keep
|
||||
* any nonexistent border pixels from floating in.
|
||||
*/
|
||||
entry->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static enum pipe_error
|
||||
brw_wm_sampler_update_default_colors(struct brw_context *brw)
|
||||
{
|
||||
enum pipe_error ret;
|
||||
int nr = MIN2(brw->curr.num_textures,
|
||||
brw->curr.num_samplers);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
const struct brw_texture *tex = brw_texture(brw->curr.texture[i]);
|
||||
const struct brw_sampler *sampler = brw->curr.sampler[i];
|
||||
const float *bc;
|
||||
|
||||
if (pf_is_depth_or_stencil(tex->base.format)) {
|
||||
float bordercolor[4] = {
|
||||
sampler->border_color[0],
|
||||
sampler->border_color[0],
|
||||
sampler->border_color[0],
|
||||
sampler->border_color[0]
|
||||
};
|
||||
|
||||
bc = bordercolor;
|
||||
}
|
||||
else {
|
||||
bc = sampler->border_color;
|
||||
}
|
||||
|
||||
/* GL specs that border color for depth textures is taken from the
|
||||
* R channel, while the hardware uses A. Spam R into all the
|
||||
* channels for safety.
|
||||
*/
|
||||
ret = upload_default_color(brw,
|
||||
bc,
|
||||
&brw->wm.sdc_bo[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* All samplers must be uploaded in a single contiguous array.
|
||||
*/
|
||||
static int upload_wm_samplers( struct brw_context *brw )
|
||||
{
|
||||
struct wm_sampler_key key;
|
||||
struct brw_winsys_reloc reloc[BRW_MAX_TEX_UNIT];
|
||||
enum pipe_error ret;
|
||||
int i;
|
||||
|
||||
brw_wm_sampler_update_default_colors(brw);
|
||||
brw_wm_sampler_populate_key(brw, &key);
|
||||
|
||||
if (brw->wm.sampler_count != key.sampler_count) {
|
||||
brw->wm.sampler_count = key.sampler_count;
|
||||
brw->state.dirty.cache |= CACHE_NEW_SAMPLER;
|
||||
}
|
||||
|
||||
if (brw->wm.sampler_count == 0) {
|
||||
bo_reference(&brw->wm.sampler_bo, NULL);
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
/* Emit SDC relocations */
|
||||
for (i = 0; i < key.sampler_count; i++) {
|
||||
make_reloc( &reloc[i],
|
||||
BRW_USAGE_SAMPLER,
|
||||
0,
|
||||
i * sizeof(struct brw_sampler_state) +
|
||||
offsetof(struct brw_sampler_state, ss2),
|
||||
brw->wm.sdc_bo[i]);
|
||||
}
|
||||
|
||||
|
||||
if (brw_search_cache(&brw->cache, BRW_SAMPLER,
|
||||
&key, sizeof(key),
|
||||
reloc, key.sampler_count,
|
||||
NULL,
|
||||
&brw->wm.sampler_bo))
|
||||
return PIPE_OK;
|
||||
|
||||
/* If we didnt find it in the cache, compute the state and put it in the
|
||||
* cache.
|
||||
*/
|
||||
ret = brw_upload_cache(&brw->cache, BRW_SAMPLER,
|
||||
&key, sizeof(key),
|
||||
reloc, key.sampler_count,
|
||||
&key.sampler, sizeof(key.sampler),
|
||||
NULL, NULL,
|
||||
&brw->wm.sampler_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_wm_samplers = {
|
||||
.dirty = {
|
||||
.mesa = PIPE_NEW_BOUND_TEXTURES | PIPE_NEW_SAMPLERS,
|
||||
.brw = 0,
|
||||
.cache = 0
|
||||
},
|
||||
.prepare = upload_wm_samplers,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_wm.h"
|
||||
#include "brw_debug.h"
|
||||
#include "brw_pipe_rast.h"
|
||||
|
||||
/***********************************************************************
|
||||
* WM unit - fragment programs and rasterization
|
||||
*/
|
||||
|
||||
struct brw_wm_unit_key {
|
||||
unsigned int total_grf, total_scratch;
|
||||
unsigned int urb_entry_read_length;
|
||||
unsigned int curb_entry_read_length;
|
||||
unsigned int dispatch_grf_start_reg;
|
||||
|
||||
unsigned int curbe_offset;
|
||||
unsigned int urb_size;
|
||||
|
||||
unsigned int max_threads;
|
||||
|
||||
unsigned int nr_surfaces, sampler_count;
|
||||
GLboolean uses_depth, computes_depth, uses_kill, has_flow_control;
|
||||
GLboolean polygon_stipple, stats_wm, line_stipple, offset_enable;
|
||||
GLfloat offset_units, offset_factor;
|
||||
};
|
||||
|
||||
static void
|
||||
wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key)
|
||||
{
|
||||
const struct brw_fragment_shader *fp = brw->curr.fragment_shader;
|
||||
|
||||
memset(key, 0, sizeof(*key));
|
||||
|
||||
if (BRW_DEBUG & DEBUG_SINGLE_THREAD)
|
||||
key->max_threads = 1;
|
||||
else {
|
||||
/* WM maximum threads is number of EUs times number of threads per EU. */
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
key->max_threads = 12 * 6;
|
||||
else if (BRW_IS_G4X(brw))
|
||||
key->max_threads = 10 * 5;
|
||||
else
|
||||
key->max_threads = 8 * 4;
|
||||
}
|
||||
|
||||
/* CACHE_NEW_WM_PROG */
|
||||
key->total_grf = brw->wm.prog_data->total_grf;
|
||||
key->urb_entry_read_length = brw->wm.prog_data->urb_read_length;
|
||||
key->curb_entry_read_length = brw->wm.prog_data->curb_read_length;
|
||||
key->dispatch_grf_start_reg = brw->wm.prog_data->first_curbe_grf;
|
||||
key->total_scratch = align(brw->wm.prog_data->total_scratch, 1024);
|
||||
|
||||
/* BRW_NEW_URB_FENCE */
|
||||
key->urb_size = brw->urb.vsize;
|
||||
|
||||
/* BRW_NEW_CURBE_OFFSETS */
|
||||
key->curbe_offset = brw->curbe.wm_start;
|
||||
|
||||
/* BRW_NEW_NR_SURFACEs */
|
||||
key->nr_surfaces = brw->wm.nr_surfaces;
|
||||
|
||||
/* CACHE_NEW_SAMPLER */
|
||||
key->sampler_count = brw->wm.sampler_count;
|
||||
|
||||
/* PIPE_NEW_RAST */
|
||||
key->polygon_stipple = brw->curr.rast->templ.poly_stipple_enable;
|
||||
|
||||
/* PIPE_NEW_FRAGMENT_PROGRAM */
|
||||
key->uses_depth = fp->uses_depth;
|
||||
key->computes_depth = fp->info.writes_z;
|
||||
|
||||
/* PIPE_NEW_DEPTH_BUFFER
|
||||
*
|
||||
* Override for NULL depthbuffer case, required by the Pixel Shader Computed
|
||||
* Depth field.
|
||||
*/
|
||||
if (brw->curr.fb.zsbuf == NULL)
|
||||
key->computes_depth = 0;
|
||||
|
||||
/* PIPE_NEW_DEPTH_STENCIL_ALPHA */
|
||||
key->uses_kill = (fp->info.uses_kill ||
|
||||
brw->curr.zstencil->cc3.alpha_test);
|
||||
|
||||
key->has_flow_control = fp->has_flow_control;
|
||||
|
||||
/* temporary sanity check assertion */
|
||||
assert(fp->has_flow_control == 0);
|
||||
|
||||
/* PIPE_NEW_QUERY */
|
||||
key->stats_wm = (brw->query.stats_wm != 0);
|
||||
|
||||
/* PIPE_NEW_RAST */
|
||||
key->line_stipple = brw->curr.rast->templ.line_stipple_enable;
|
||||
|
||||
|
||||
key->offset_enable = (brw->curr.rast->templ.offset_cw ||
|
||||
brw->curr.rast->templ.offset_ccw);
|
||||
|
||||
key->offset_units = brw->curr.rast->templ.offset_units;
|
||||
key->offset_factor = brw->curr.rast->templ.offset_scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup wm hardware state. See page 225 of Volume 2
|
||||
*/
|
||||
static enum pipe_error
|
||||
wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
|
||||
struct brw_winsys_reloc *reloc,
|
||||
unsigned nr_reloc,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
struct brw_wm_unit_state wm;
|
||||
enum pipe_error ret;
|
||||
|
||||
memset(&wm, 0, sizeof(wm));
|
||||
|
||||
wm.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
|
||||
wm.thread0.kernel_start_pointer = 0; /* reloc */
|
||||
wm.thread1.depth_coef_urb_read_offset = 1;
|
||||
wm.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
|
||||
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
wm.thread1.binding_table_entry_count = 0; /* hardware requirement */
|
||||
else
|
||||
wm.thread1.binding_table_entry_count = key->nr_surfaces;
|
||||
|
||||
if (key->total_scratch != 0) {
|
||||
wm.thread2.scratch_space_base_pointer = 0; /* reloc */
|
||||
wm.thread2.per_thread_scratch_space = key->total_scratch / 1024 - 1;
|
||||
} else {
|
||||
wm.thread2.scratch_space_base_pointer = 0;
|
||||
wm.thread2.per_thread_scratch_space = 0;
|
||||
}
|
||||
|
||||
wm.thread3.dispatch_grf_start_reg = key->dispatch_grf_start_reg;
|
||||
wm.thread3.urb_entry_read_length = key->urb_entry_read_length;
|
||||
wm.thread3.urb_entry_read_offset = 0;
|
||||
wm.thread3.const_urb_entry_read_length = key->curb_entry_read_length;
|
||||
wm.thread3.const_urb_entry_read_offset = key->curbe_offset * 2;
|
||||
|
||||
if (BRW_IS_IGDNG(brw))
|
||||
wm.wm4.sampler_count = 0; /* hardware requirement */
|
||||
else
|
||||
wm.wm4.sampler_count = (key->sampler_count + 1) / 4;
|
||||
|
||||
/* reloc */
|
||||
wm.wm4.sampler_state_pointer = 0;
|
||||
|
||||
wm.wm5.program_uses_depth = key->uses_depth;
|
||||
wm.wm5.program_computes_depth = key->computes_depth;
|
||||
wm.wm5.program_uses_killpixel = key->uses_kill;
|
||||
|
||||
if (key->has_flow_control)
|
||||
wm.wm5.enable_8_pix = 1;
|
||||
else
|
||||
wm.wm5.enable_16_pix = 1;
|
||||
|
||||
wm.wm5.max_threads = key->max_threads - 1;
|
||||
wm.wm5.thread_dispatch_enable = 1; /* AKA: color_write */
|
||||
wm.wm5.legacy_line_rast = 0;
|
||||
wm.wm5.legacy_global_depth_bias = 0;
|
||||
wm.wm5.early_depth_test = 1; /* never need to disable */
|
||||
wm.wm5.line_aa_region_width = 0;
|
||||
wm.wm5.line_endcap_aa_region_width = 1;
|
||||
|
||||
wm.wm5.polygon_stipple = key->polygon_stipple;
|
||||
|
||||
if (key->offset_enable) {
|
||||
wm.wm5.depth_offset = 1;
|
||||
/* Something wierd going on with legacy_global_depth_bias,
|
||||
* offset_constant, scaling and MRD. This value passes glean
|
||||
* but gives some odd results elsewere (eg. the
|
||||
* quad-offset-units test).
|
||||
*/
|
||||
wm.global_depth_offset_constant = key->offset_units * 2;
|
||||
|
||||
/* This is the only value that passes glean:
|
||||
*/
|
||||
wm.global_depth_offset_scale = key->offset_factor;
|
||||
}
|
||||
|
||||
wm.wm5.line_stipple = key->line_stipple;
|
||||
|
||||
if ((BRW_DEBUG & DEBUG_STATS) || key->stats_wm)
|
||||
wm.wm4.stats_enable = 1;
|
||||
|
||||
ret = brw_upload_cache(&brw->cache, BRW_WM_UNIT,
|
||||
key, sizeof(*key),
|
||||
reloc, nr_reloc,
|
||||
&wm, sizeof(wm),
|
||||
NULL, NULL,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
static enum pipe_error upload_wm_unit( struct brw_context *brw )
|
||||
{
|
||||
struct brw_wm_unit_key key;
|
||||
struct brw_winsys_reloc reloc[3];
|
||||
unsigned nr_reloc = 0;
|
||||
enum pipe_error ret;
|
||||
unsigned grf_reg_count;
|
||||
unsigned per_thread_scratch_space;
|
||||
unsigned stats_enable;
|
||||
unsigned sampler_count;
|
||||
|
||||
wm_unit_populate_key(brw, &key);
|
||||
|
||||
|
||||
/* Allocate the necessary scratch space if we haven't already. Don't
|
||||
* bother reducing the allocation later, since we use scratch so
|
||||
* rarely.
|
||||
*/
|
||||
assert(key.total_scratch <= 12 * 1024);
|
||||
if (key.total_scratch) {
|
||||
GLuint total = key.total_scratch * key.max_threads;
|
||||
|
||||
/* Do we need a new buffer:
|
||||
*/
|
||||
if (brw->wm.scratch_bo && total > brw->wm.scratch_bo->size)
|
||||
bo_reference(&brw->wm.scratch_bo, NULL);
|
||||
|
||||
if (brw->wm.scratch_bo == NULL) {
|
||||
ret = brw->sws->bo_alloc(brw->sws,
|
||||
BRW_BUFFER_TYPE_SHADER_SCRATCH,
|
||||
total,
|
||||
4096,
|
||||
&brw->wm.scratch_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* XXX: temporary:
|
||||
*/
|
||||
grf_reg_count = (align(key.total_grf, 16) / 16 - 1);
|
||||
per_thread_scratch_space = key.total_scratch / 1024 - 1;
|
||||
stats_enable = (BRW_DEBUG & DEBUG_STATS) || key.stats_wm;
|
||||
sampler_count = BRW_IS_IGDNG(brw) ? 0 :(key.sampler_count + 1) / 4;
|
||||
|
||||
/* Emit WM program relocation */
|
||||
make_reloc(&reloc[nr_reloc++],
|
||||
BRW_USAGE_STATE,
|
||||
grf_reg_count << 1,
|
||||
offsetof(struct brw_wm_unit_state, thread0),
|
||||
brw->wm.prog_bo);
|
||||
|
||||
/* Emit scratch space relocation */
|
||||
if (key.total_scratch != 0) {
|
||||
make_reloc(&reloc[nr_reloc++],
|
||||
BRW_USAGE_SCRATCH,
|
||||
per_thread_scratch_space,
|
||||
offsetof(struct brw_wm_unit_state, thread2),
|
||||
brw->wm.scratch_bo);
|
||||
}
|
||||
|
||||
/* Emit sampler state relocation */
|
||||
if (key.sampler_count != 0) {
|
||||
make_reloc(&reloc[nr_reloc++],
|
||||
BRW_USAGE_STATE,
|
||||
stats_enable | (sampler_count << 2),
|
||||
offsetof(struct brw_wm_unit_state, wm4),
|
||||
brw->wm.sampler_bo);
|
||||
}
|
||||
|
||||
|
||||
if (brw_search_cache(&brw->cache, BRW_WM_UNIT,
|
||||
&key, sizeof(key),
|
||||
reloc, nr_reloc,
|
||||
NULL,
|
||||
&brw->wm.state_bo))
|
||||
return PIPE_OK;
|
||||
|
||||
ret = wm_unit_create_from_key(brw, &key,
|
||||
reloc, nr_reloc,
|
||||
&brw->wm.state_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_wm_unit = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_FRAGMENT_SHADER |
|
||||
PIPE_NEW_DEPTH_BUFFER |
|
||||
PIPE_NEW_RAST |
|
||||
PIPE_NEW_DEPTH_STENCIL_ALPHA |
|
||||
PIPE_NEW_QUERY),
|
||||
|
||||
.brw = (BRW_NEW_CURBE_OFFSETS |
|
||||
BRW_NEW_NR_WM_SURFACES),
|
||||
|
||||
.cache = (CACHE_NEW_WM_PROG |
|
||||
CACHE_NEW_SAMPLER)
|
||||
},
|
||||
.prepare = upload_wm_unit,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
||||
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
|
||||
develop this 3D driver.
|
||||
|
||||
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, sublicense, 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 NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
|
||||
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "pipe/p_format.h"
|
||||
|
||||
#include "brw_batchbuffer.h"
|
||||
#include "brw_context.h"
|
||||
#include "brw_state.h"
|
||||
#include "brw_defines.h"
|
||||
#include "brw_screen.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static enum pipe_error
|
||||
brw_update_texture_surface( struct brw_context *brw,
|
||||
struct brw_texture *tex,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
struct brw_winsys_reloc reloc[1];
|
||||
enum pipe_error ret;
|
||||
|
||||
/* Emit relocation to surface contents */
|
||||
make_reloc(&reloc[0],
|
||||
BRW_USAGE_SAMPLER,
|
||||
0,
|
||||
offsetof(struct brw_surface_state, ss1),
|
||||
tex->bo);
|
||||
|
||||
if (brw_search_cache(&brw->surface_cache,
|
||||
BRW_SS_SURFACE,
|
||||
&tex->ss, sizeof tex->ss,
|
||||
reloc, Elements(reloc),
|
||||
NULL,
|
||||
bo_out))
|
||||
return PIPE_OK;
|
||||
|
||||
ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
|
||||
&tex->ss, sizeof tex->ss,
|
||||
reloc, Elements(reloc),
|
||||
&tex->ss, sizeof tex->ss,
|
||||
NULL, NULL,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sets up a surface state structure to point at the given region.
|
||||
* While it is only used for the front/back buffer currently, it should be
|
||||
* usable for further buffers when doing ARB_draw_buffer support.
|
||||
*/
|
||||
static enum pipe_error
|
||||
brw_update_render_surface(struct brw_context *brw,
|
||||
struct brw_surface *surface,
|
||||
struct brw_winsys_buffer **bo_out)
|
||||
{
|
||||
struct brw_surf_ss0 blend_ss0 = brw->curr.blend->ss0;
|
||||
struct brw_surface_state ss;
|
||||
struct brw_winsys_reloc reloc[1];
|
||||
enum pipe_error ret;
|
||||
|
||||
/* XXX: we will only be rendering to this surface:
|
||||
*/
|
||||
make_reloc(&reloc[0],
|
||||
BRW_USAGE_RENDER_TARGET,
|
||||
0,
|
||||
offsetof(struct brw_surface_state, ss1),
|
||||
surface->bo);
|
||||
|
||||
/* Surfaces are potentially shared between contexts, so can't
|
||||
* scribble the in-place ss0 value in the surface.
|
||||
*/
|
||||
memcpy(&ss, &surface->ss, sizeof ss);
|
||||
|
||||
ss.ss0.color_blend = blend_ss0.color_blend;
|
||||
ss.ss0.writedisable_blue = blend_ss0.writedisable_blue;
|
||||
ss.ss0.writedisable_green = blend_ss0.writedisable_green;
|
||||
ss.ss0.writedisable_red = blend_ss0.writedisable_red;
|
||||
ss.ss0.writedisable_alpha = blend_ss0.writedisable_alpha;
|
||||
|
||||
if (brw_search_cache(&brw->surface_cache,
|
||||
BRW_SS_SURFACE,
|
||||
&ss, sizeof(ss),
|
||||
reloc, Elements(reloc),
|
||||
NULL,
|
||||
bo_out))
|
||||
return PIPE_OK;
|
||||
|
||||
ret = brw_upload_cache(&brw->surface_cache,
|
||||
BRW_SS_SURFACE,
|
||||
&ss, sizeof ss,
|
||||
reloc, Elements(reloc),
|
||||
&ss, sizeof ss,
|
||||
NULL, NULL,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs the binding table for the WM surface state, which maps unit
|
||||
* numbers to surface state objects.
|
||||
*/
|
||||
static enum pipe_error
|
||||
brw_wm_get_binding_table(struct brw_context *brw,
|
||||
struct brw_winsys_buffer **bo_out )
|
||||
{
|
||||
enum pipe_error ret;
|
||||
struct brw_winsys_reloc reloc[BRW_WM_MAX_SURF];
|
||||
uint32_t data[BRW_WM_MAX_SURF];
|
||||
GLuint nr_relocs = 0;
|
||||
GLuint data_size = brw->wm.nr_surfaces * sizeof data[0];
|
||||
int i;
|
||||
|
||||
assert(brw->wm.nr_surfaces <= BRW_WM_MAX_SURF);
|
||||
assert(brw->wm.nr_surfaces > 0);
|
||||
|
||||
/* Emit binding table relocations to surface state
|
||||
*/
|
||||
for (i = 0; i < brw->wm.nr_surfaces; i++) {
|
||||
if (brw->wm.surf_bo[i]) {
|
||||
make_reloc(&reloc[nr_relocs++],
|
||||
BRW_USAGE_STATE,
|
||||
0,
|
||||
i * sizeof(GLuint),
|
||||
brw->wm.surf_bo[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Note there is no key for this search beyond the values in the
|
||||
* relocation array:
|
||||
*/
|
||||
if (brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
|
||||
NULL, 0,
|
||||
reloc, nr_relocs,
|
||||
NULL,
|
||||
bo_out))
|
||||
return PIPE_OK;
|
||||
|
||||
/* Upload zero data, will all be overwitten with relocation
|
||||
* offsets:
|
||||
*/
|
||||
for (i = 0; i < brw->wm.nr_surfaces; i++)
|
||||
data[i] = 0;
|
||||
|
||||
ret = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
|
||||
NULL, 0,
|
||||
reloc, nr_relocs,
|
||||
data, data_size,
|
||||
NULL, NULL,
|
||||
bo_out);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
static enum pipe_error prepare_wm_surfaces(struct brw_context *brw )
|
||||
{
|
||||
enum pipe_error ret;
|
||||
int nr_surfaces = 0;
|
||||
GLuint i;
|
||||
|
||||
/* PIPE_NEW_COLOR_BUFFERS | PIPE_NEW_BLEND
|
||||
*
|
||||
* Update surfaces for drawing buffers. Mixes in colormask and
|
||||
* blend state.
|
||||
*
|
||||
* XXX: no color buffer case
|
||||
*/
|
||||
for (i = 0; i < brw->curr.fb.nr_cbufs; i++) {
|
||||
ret = brw_update_render_surface(brw,
|
||||
brw_surface(brw->curr.fb.cbufs[i]),
|
||||
&brw->wm.surf_bo[BTI_COLOR_BUF(i)]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nr_surfaces = BTI_COLOR_BUF(i) + 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* PIPE_NEW_FRAGMENT_CONSTANTS
|
||||
*/
|
||||
#if 0
|
||||
if (brw->curr.fragment_constants) {
|
||||
ret = brw_update_fragment_constant_surface(
|
||||
brw,
|
||||
brw->curr.fragment_constants,
|
||||
&brw->wm.surf_bo[BTI_FRAGMENT_CONSTANTS]);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nr_surfaces = BTI_FRAGMENT_CONSTANTS + 1;
|
||||
}
|
||||
else {
|
||||
bo_reference(&brw->wm.surf_bo[SURF_FRAG_CONSTANTS], NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* PIPE_NEW_TEXTURE
|
||||
*/
|
||||
for (i = 0; i < brw->curr.num_textures; i++) {
|
||||
ret = brw_update_texture_surface(brw,
|
||||
brw_texture(brw->curr.texture[i]),
|
||||
&brw->wm.surf_bo[BTI_TEXTURE(i)]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nr_surfaces = BTI_TEXTURE(i) + 1;
|
||||
}
|
||||
|
||||
/* Clear any inactive entries:
|
||||
*/
|
||||
for (i = brw->curr.fb.nr_cbufs; i < BRW_MAX_DRAW_BUFFERS; i++)
|
||||
bo_reference(&brw->wm.surf_bo[BTI_COLOR_BUF(i)], NULL);
|
||||
|
||||
if (!brw->curr.fragment_constants)
|
||||
bo_reference(&brw->wm.surf_bo[BTI_FRAGMENT_CONSTANTS], NULL);
|
||||
|
||||
/* XXX: no pipe_max_textures define?? */
|
||||
for (i = brw->curr.num_textures; i < PIPE_MAX_SAMPLERS; i++)
|
||||
bo_reference(&brw->wm.surf_bo[BTI_TEXTURE(i)], NULL);
|
||||
|
||||
if (brw->wm.nr_surfaces != nr_surfaces) {
|
||||
brw->wm.nr_surfaces = nr_surfaces;
|
||||
brw->state.dirty.brw |= BRW_NEW_NR_WM_SURFACES;
|
||||
}
|
||||
|
||||
ret = brw_wm_get_binding_table(brw, &brw->wm.bind_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
||||
const struct brw_tracked_state brw_wm_surfaces = {
|
||||
.dirty = {
|
||||
.mesa = (PIPE_NEW_COLOR_BUFFERS |
|
||||
PIPE_NEW_BOUND_TEXTURES |
|
||||
PIPE_NEW_FRAGMENT_CONSTANTS |
|
||||
PIPE_NEW_BLEND),
|
||||
.brw = (BRW_NEW_CONTEXT |
|
||||
BRW_NEW_WM_SURFACES),
|
||||
.cache = 0
|
||||
},
|
||||
.prepare = prepare_wm_surfaces,
|
||||
};
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright © 2007 Intel Corporation
|
||||
*
|
||||
* 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, sublicense,
|
||||
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
int intel_decode(const uint32_t *data, int count, uint32_t hw_offset, uint32_t devid);
|
||||
void intel_decode_context_reset(void);
|
||||
@@ -0,0 +1,132 @@
|
||||
#ifndef INTEL_STRUCTS_H
|
||||
#define INTEL_STRUCTS_H
|
||||
|
||||
struct br0 {
|
||||
GLuint length:8;
|
||||
GLuint pad0:3;
|
||||
GLuint dst_tiled:1;
|
||||
GLuint pad1:8;
|
||||
GLuint write_rgb:1;
|
||||
GLuint write_alpha:1;
|
||||
GLuint opcode:7;
|
||||
GLuint client:3;
|
||||
};
|
||||
|
||||
|
||||
struct br13 {
|
||||
GLint dest_pitch:16;
|
||||
GLuint rop:8;
|
||||
GLuint color_depth:2;
|
||||
GLuint pad1:3;
|
||||
GLuint mono_source_transparency:1;
|
||||
GLuint clipping_enable:1;
|
||||
GLuint pad0:1;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* This is an attempt to move some of the 2D interaction in this
|
||||
* driver to using structs for packets rather than a bunch of #defines
|
||||
* and dwords.
|
||||
*/
|
||||
struct xy_color_blit {
|
||||
struct br0 br0;
|
||||
struct br13 br13;
|
||||
|
||||
struct {
|
||||
GLuint dest_x1:16;
|
||||
GLuint dest_y1:16;
|
||||
} dw2;
|
||||
|
||||
struct {
|
||||
GLuint dest_x2:16;
|
||||
GLuint dest_y2:16;
|
||||
} dw3;
|
||||
|
||||
GLuint dest_base_addr;
|
||||
GLuint color;
|
||||
};
|
||||
|
||||
struct xy_src_copy_blit {
|
||||
struct br0 br0;
|
||||
struct br13 br13;
|
||||
|
||||
struct {
|
||||
GLuint dest_x1:16;
|
||||
GLuint dest_y1:16;
|
||||
} dw2;
|
||||
|
||||
struct {
|
||||
GLuint dest_x2:16;
|
||||
GLuint dest_y2:16;
|
||||
} dw3;
|
||||
|
||||
GLuint dest_base_addr;
|
||||
|
||||
struct {
|
||||
GLuint src_x1:16;
|
||||
GLuint src_y1:16;
|
||||
} dw5;
|
||||
|
||||
struct {
|
||||
GLint src_pitch:16;
|
||||
GLuint pad:16;
|
||||
} dw6;
|
||||
|
||||
GLuint src_base_addr;
|
||||
};
|
||||
|
||||
struct xy_setup_blit {
|
||||
struct br0 br0;
|
||||
struct br13 br13;
|
||||
|
||||
struct {
|
||||
GLuint clip_x1:16;
|
||||
GLuint clip_y1:16;
|
||||
} dw2;
|
||||
|
||||
struct {
|
||||
GLuint clip_x2:16;
|
||||
GLuint clip_y2:16;
|
||||
} dw3;
|
||||
|
||||
GLuint dest_base_addr;
|
||||
GLuint background_color;
|
||||
GLuint foreground_color;
|
||||
GLuint pattern_base_addr;
|
||||
};
|
||||
|
||||
|
||||
struct xy_text_immediate_blit {
|
||||
struct {
|
||||
GLuint length:8;
|
||||
GLuint pad2:3;
|
||||
GLuint dst_tiled:1;
|
||||
GLuint pad1:4;
|
||||
GLuint byte_packed:1;
|
||||
GLuint pad0:5;
|
||||
GLuint opcode:7;
|
||||
GLuint client:3;
|
||||
} dw0;
|
||||
|
||||
struct {
|
||||
GLuint dest_x1:16;
|
||||
GLuint dest_y1:16;
|
||||
} dw1;
|
||||
|
||||
struct {
|
||||
GLuint dest_x2:16;
|
||||
GLuint dest_y2:16;
|
||||
} dw2;
|
||||
|
||||
/* Src bitmap data follows as inline dwords.
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
#define CLIENT_2D 0x2
|
||||
#define OPCODE_XY_SETUP_BLT 0x1
|
||||
#define OPCODE_XY_COLOR_BLT 0x50
|
||||
#define OPCODE_XY_TEXT_IMMEDIATE_BLT 0x31
|
||||
|
||||
#endif
|
||||
@@ -58,6 +58,11 @@ if env['dri']:
|
||||
'intel/SConscript',
|
||||
])
|
||||
|
||||
if 'i965' in env['winsys']:
|
||||
SConscript([
|
||||
'i965/SConscript',
|
||||
])
|
||||
|
||||
if 'radeon' in env['winsys']:
|
||||
SConscript([
|
||||
'radeon/SConscript',
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# src/gallium/winsys/drm/intel/Makefile
|
||||
TOP = ../../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
SUBDIRS = gem $(GALLIUM_STATE_TRACKERS_DIRS)
|
||||
|
||||
default install clean:
|
||||
@for dir in $(SUBDIRS) ; do \
|
||||
if [ -d $$dir ] ; then \
|
||||
(cd $$dir && $(MAKE) $@) || exit 1; \
|
||||
fi \
|
||||
done
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user