summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/freedreno/Makefile.sources1
-rw-r--r--src/gallium/drivers/freedreno/a2xx/fd2_context.c1
-rw-r--r--src/gallium/drivers/freedreno/a2xx/fd2_program.c35
-rw-r--r--src/gallium/drivers/freedreno/a2xx/fd2_program.h1
-rw-r--r--src/gallium/drivers/freedreno/a3xx/fd3_context.c2
-rw-r--r--src/gallium/drivers/freedreno/a3xx/fd3_program.c259
-rw-r--r--src/gallium/drivers/freedreno/a3xx/fd3_program.h1
-rw-r--r--src/gallium/drivers/freedreno/freedreno_context.c3
-rw-r--r--src/gallium/drivers/freedreno/freedreno_program.c128
-rw-r--r--src/gallium/drivers/freedreno/freedreno_program.h37
10 files changed, 181 insertions, 287 deletions
diff --git a/src/gallium/drivers/freedreno/Makefile.sources b/src/gallium/drivers/freedreno/Makefile.sources
index 05a12fb318c..311b0b6a205 100644
--- a/src/gallium/drivers/freedreno/Makefile.sources
+++ b/src/gallium/drivers/freedreno/Makefile.sources
@@ -1,6 +1,7 @@
C_SOURCES := \
freedreno_util.c \
freedreno_lowering.c \
+ freedreno_program.c \
freedreno_query.c \
freedreno_fence.c \
freedreno_resource.c \
diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_context.c b/src/gallium/drivers/freedreno/a2xx/fd2_context.c
index 239558b6f07..f51c5eead4f 100644
--- a/src/gallium/drivers/freedreno/a2xx/fd2_context.c
+++ b/src/gallium/drivers/freedreno/a2xx/fd2_context.c
@@ -40,7 +40,6 @@
static void
fd2_context_destroy(struct pipe_context *pctx)
{
- fd2_prog_fini(pctx);
fd_context_destroy(pctx);
}
diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_program.c b/src/gallium/drivers/freedreno/a2xx/fd2_program.c
index c62a7f90b98..84b6ffec338 100644
--- a/src/gallium/drivers/freedreno/a2xx/fd2_program.c
+++ b/src/gallium/drivers/freedreno/a2xx/fd2_program.c
@@ -34,6 +34,8 @@
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_parse.h"
+#include "freedreno_program.h"
+
#include "fd2_program.h"
#include "fd2_compiler.h"
#include "fd2_texture.h"
@@ -141,15 +143,6 @@ fd2_fp_state_delete(struct pipe_context *pctx, void *hwcso)
delete_shader(so);
}
-static void
-fd2_fp_state_bind(struct pipe_context *pctx, void *hwcso)
-{
- struct fd_context *ctx = fd_context(pctx);
- ctx->prog.fp = hwcso;
- ctx->prog.dirty |= FD_SHADER_DIRTY_FP;
- ctx->dirty |= FD_DIRTY_PROG;
-}
-
static void *
fd2_vp_state_create(struct pipe_context *pctx,
const struct pipe_shader_state *cso)
@@ -169,15 +162,6 @@ fd2_vp_state_delete(struct pipe_context *pctx, void *hwcso)
}
static void
-fd2_vp_state_bind(struct pipe_context *pctx, void *hwcso)
-{
- struct fd_context *ctx = fd_context(pctx);
- ctx->prog.vp = hwcso;
- ctx->prog.dirty |= FD_SHADER_DIRTY_VP;
- ctx->dirty |= FD_DIRTY_PROG;
-}
-
-static void
patch_vtx_fetches(struct fd_context *ctx, struct fd2_shader_stateobj *so,
struct fd_vertex_stateobj *vtx)
{
@@ -481,26 +465,15 @@ fd2_prog_init(struct pipe_context *pctx)
struct fd_context *ctx = fd_context(pctx);
pctx->create_fs_state = fd2_fp_state_create;
- pctx->bind_fs_state = fd2_fp_state_bind;
pctx->delete_fs_state = fd2_fp_state_delete;
pctx->create_vs_state = fd2_vp_state_create;
- pctx->bind_vs_state = fd2_vp_state_bind;
pctx->delete_vs_state = fd2_vp_state_delete;
+ fd_prog_init(pctx);
+
ctx->solid_prog.fp = create_solid_fp();
ctx->solid_prog.vp = create_solid_vp();
ctx->blit_prog.fp = create_blit_fp();
ctx->blit_prog.vp = create_blit_vp();
}
-
-void
-fd2_prog_fini(struct pipe_context *pctx)
-{
- struct fd_context *ctx = fd_context(pctx);
-
- delete_shader(ctx->solid_prog.vp);
- delete_shader(ctx->solid_prog.fp);
- delete_shader(ctx->blit_prog.vp);
- delete_shader(ctx->blit_prog.fp);
-}
diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_program.h b/src/gallium/drivers/freedreno/a2xx/fd2_program.h
index 393cb616f63..170b22abee0 100644
--- a/src/gallium/drivers/freedreno/a2xx/fd2_program.h
+++ b/src/gallium/drivers/freedreno/a2xx/fd2_program.h
@@ -77,6 +77,5 @@ void fd2_program_emit(struct fd_ringbuffer *ring,
void fd2_program_validate(struct fd_context *ctx);
void fd2_prog_init(struct pipe_context *pctx);
-void fd2_prog_fini(struct pipe_context *pctx);
#endif /* FD2_PROGRAM_H_ */
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_context.c b/src/gallium/drivers/freedreno/a3xx/fd3_context.c
index 8273e9a1a77..f36cbd946a0 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_context.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_context.c
@@ -42,8 +42,6 @@ fd3_context_destroy(struct pipe_context *pctx)
{
struct fd3_context *fd3_ctx = fd3_context(fd_context(pctx));
- fd3_prog_fini(pctx);
-
util_dynarray_fini(&fd3_ctx->rbrc_patches);
fd_bo_del(fd3_ctx->vs_pvt_mem);
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_program.c b/src/gallium/drivers/freedreno/a3xx/fd3_program.c
index 0fd759e94f1..c6fb8633cd0 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_program.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_program.c
@@ -35,6 +35,7 @@
#include "tgsi/tgsi_parse.h"
#include "freedreno_lowering.h"
+#include "freedreno_program.h"
#include "fd3_program.h"
#include "fd3_compiler.h"
@@ -165,15 +166,6 @@ fd3_fp_state_delete(struct pipe_context *pctx, void *hwcso)
delete_shader(so);
}
-static void
-fd3_fp_state_bind(struct pipe_context *pctx, void *hwcso)
-{
- struct fd_context *ctx = fd_context(pctx);
- ctx->prog.fp = hwcso;
- ctx->prog.dirty |= FD_SHADER_DIRTY_FP;
- ctx->dirty |= FD_DIRTY_PROG;
-}
-
static void *
fd3_vp_state_create(struct pipe_context *pctx,
const struct pipe_shader_state *cso)
@@ -189,15 +181,6 @@ fd3_vp_state_delete(struct pipe_context *pctx, void *hwcso)
}
static void
-fd3_vp_state_bind(struct pipe_context *pctx, void *hwcso)
-{
- struct fd_context *ctx = fd_context(pctx);
- ctx->prog.vp = hwcso;
- ctx->prog.dirty |= FD_SHADER_DIRTY_VP;
- ctx->dirty |= FD_DIRTY_PROG;
-}
-
-static void
emit_shader(struct fd_ringbuffer *ring, const struct fd3_shader_stateobj *so)
{
const struct ir3_shader_info *si = &so->info;
@@ -476,255 +459,29 @@ fd3_program_emit(struct fd_ringbuffer *ring,
A3XX_VFD_CONTROL_1_REGID4INST(regid(63,0)));
}
-/* once the compiler is good enough, we should construct TGSI in the
- * core freedreno driver, and then let the a2xx/a3xx parts compile
- * the internal shaders from TGSI the same as regular shaders. This
- * would be the first step towards handling most of clear (and the
- * gmem<->mem blits) from the core via normal state changes and shader
- * state objects.
- *
- * (Well, there would still be some special bits, because there are
- * some registers that don't get set for normal draw, but this should
- * be relatively small and could be handled via callbacks from core
- * into a2xx/a3xx..)
- */
-static struct fd3_shader_stateobj *
-create_internal_shader(struct pipe_context *pctx, enum shader_t type,
- struct ir3_shader *ir)
-{
- struct fd3_shader_stateobj *so = CALLOC_STRUCT(fd3_shader_stateobj);
-
- if (!so) {
- ir3_shader_destroy(ir);
- return NULL;
- }
-
- so->type = type;
- so->ir = ir;
-
- assemble_shader(pctx, so);
- assert(so->bo);
-
- return so;
-}
-
-/* Creates shader:
- * (sy)(ss)(rpt1)bary.f (ei)r0.z, (r)0, r0.x
- * (rpt5)nop
- * sam (f32)(xyzw)r0.x, r0.z, s#0, t#0
- * (sy)(rpt3)cov.f32f16 hr0.x, (r)r0.x
- * end
- */
-static struct fd3_shader_stateobj *
-create_blit_fp(struct pipe_context *pctx)
+/* hack.. until we figure out how to deal w/ vpsrepl properly.. */
+static void
+fix_blit_fp(struct pipe_context *pctx)
{
- struct fd3_shader_stateobj *so;
- struct ir3_shader *ir = ir3_shader_create();
- struct ir3_block *block = ir3_block_create(ir, 0, 0, 0);
- struct ir3_instruction *instr;
-
- /* (sy)(ss)(rpt1)bary.f (ei)r0.z, (r)0, r0.x */
- instr = ir3_instr_create(block, 2, OPC_BARY_F);
- instr->flags = IR3_INSTR_SY | IR3_INSTR_SS;
- instr->repeat = 1;
-
- ir3_reg_create(instr, regid(0,2), IR3_REG_EI); /* (ei)r0.z */
- ir3_reg_create(instr, 0, IR3_REG_R | /* (r)0 */
- IR3_REG_IMMED)->iim_val = 0;
- ir3_reg_create(instr, regid(0,0), 0); /* r0.x */
-
- /* (rpt5)nop */
- instr = ir3_instr_create(block, 0, OPC_NOP);
- instr->repeat = 5;
-
- /* sam (f32)(xyzw)r0.x, r0.z, s#0, t#0 */
- instr = ir3_instr_create(block, 5, OPC_SAM);
- instr->cat5.samp = 0;
- instr->cat5.tex = 0;
- instr->cat5.type = TYPE_F32;
-
- ir3_reg_create(instr, regid(0,0), /* (xyzw)r0.x */
- 0)->wrmask = 0xf;
- ir3_reg_create(instr, regid(0,2), 0); /* r0.z */
-
- /* (sy)(rpt3)cov.f32f16 hr0.x, (r)r0.x */
- instr = ir3_instr_create(block, 1, 0); /* mov/cov instructions have no opc */
- instr->flags = IR3_INSTR_SY;
- instr->repeat = 3;
- instr->cat1.src_type = TYPE_F32;
- instr->cat1.dst_type = TYPE_F16;
-
- ir3_reg_create(instr, regid(0,0), IR3_REG_HALF); /* hr0.x */
- ir3_reg_create(instr, regid(0,0), IR3_REG_R); /* (r)r0.x */
-
- /* end */
- instr = ir3_instr_create(block, 0, OPC_END);
-
- so = create_internal_shader(pctx, SHADER_FRAGMENT, ir);
- if (!so)
- return NULL;
-
- so->half_precision = true;
- so->inputs_count = 1;
- so->inputs[0].semantic =
- fd3_semantic_name(TGSI_SEMANTIC_TEXCOORD, 0);
- so->inputs[0].inloc = 8;
- so->inputs[0].compmask = 0x3;
- so->total_in = 2;
- so->outputs_count = 1;
- so->outputs[0].semantic =
- fd3_semantic_name(TGSI_SEMANTIC_COLOR, 0);
- so->outputs[0].regid = regid(0,0);
- so->samplers_count = 1;
+ struct fd_context *ctx = fd_context(pctx);
+ struct fd3_shader_stateobj *so = ctx->blit_prog.fp;
so->vpsrepl[0] = 0x99999999;
so->vpsrepl[1] = 0x99999999;
so->vpsrepl[2] = 0x99999999;
so->vpsrepl[3] = 0x99999999;
-
- return so;
-}
-
-/* Creates shader:
- * (sy)(ss)end
- */
-static struct fd3_shader_stateobj *
-create_blit_vp(struct pipe_context *pctx)
-{
- struct fd3_shader_stateobj *so;
- struct ir3_shader *ir = ir3_shader_create();
- struct ir3_block *block = ir3_block_create(ir, 0, 0, 0);
- struct ir3_instruction *instr;
-
- /* (sy)(ss)end */
- instr = ir3_instr_create(block, 0, OPC_END);
- instr->flags = IR3_INSTR_SY | IR3_INSTR_SS;
-
- so = create_internal_shader(pctx, SHADER_VERTEX, ir);
- if (!so)
- return NULL;
-
- so->inputs_count = 2;
- so->inputs[0].regid = regid(0,0);
- so->inputs[0].compmask = 0xf;
- so->inputs[1].regid = regid(1,0);
- so->inputs[1].compmask = 0xf;
- so->total_in = 8;
- so->outputs_count = 2;
- so->outputs[0].semantic =
- fd3_semantic_name(TGSI_SEMANTIC_TEXCOORD, 0);
- so->outputs[0].regid = regid(0,0);
- so->outputs[1].semantic =
- fd3_semantic_name(TGSI_SEMANTIC_POSITION, 0);
- so->outputs[1].regid = regid(1,0);
-
- fixup_vp_regfootprint(so);
-
- return so;
-}
-
-/* Creates shader:
- * (sy)(ss)(rpt3)mov.f16f16 hr0.x, (r)hc0.x
- * end
- */
-static struct fd3_shader_stateobj *
-create_solid_fp(struct pipe_context *pctx)
-{
- struct fd3_shader_stateobj *so;
- struct ir3_shader *ir = ir3_shader_create();
- struct ir3_block *block = ir3_block_create(ir, 0, 0, 0);
- struct ir3_instruction *instr;
-
- /* (sy)(ss)(rpt3)mov.f16f16 hr0.x, (r)hc0.x */
- instr = ir3_instr_create(block, 1, 0); /* mov/cov instructions have no opc */
- instr->flags = IR3_INSTR_SY | IR3_INSTR_SS;
- instr->repeat = 3;
- instr->cat1.src_type = TYPE_F16;
- instr->cat1.dst_type = TYPE_F16;
-
- ir3_reg_create(instr, regid(0,0), IR3_REG_HALF); /* hr0.x */
- ir3_reg_create(instr, regid(0,0), IR3_REG_HALF | /* (r)hc0.x */
- IR3_REG_CONST | IR3_REG_R);
-
- /* end */
- instr = ir3_instr_create(block, 0, OPC_END);
-
- so = create_internal_shader(pctx, SHADER_FRAGMENT, ir);
- if (!so)
- return NULL;
-
- so->half_precision = true;
- so->inputs_count = 0;
- so->outputs_count = 1;
- so->outputs[0].semantic =
- fd3_semantic_name(TGSI_SEMANTIC_COLOR, 0);
- so->outputs[0].regid = regid(0, 0);
- so->total_in = 0;
-
- return so;
-}
-
-/* Creates shader:
- * (sy)(ss)end
- */
-static struct fd3_shader_stateobj *
-create_solid_vp(struct pipe_context *pctx)
-{
- struct fd3_shader_stateobj *so;
- struct ir3_shader *ir = ir3_shader_create();
- struct ir3_block *block = ir3_block_create(ir, 0, 0, 0);
- struct ir3_instruction *instr;
-
- /* (sy)(ss)end */
- instr = ir3_instr_create(block, 0, OPC_END);
- instr->flags = IR3_INSTR_SY | IR3_INSTR_SS;
-
-
- so = create_internal_shader(pctx, SHADER_VERTEX, ir);
- if (!so)
- return NULL;
-
- so->inputs_count = 1;
- so->inputs[0].regid = regid(0,0);
- so->inputs[0].compmask = 0xf;
- so->total_in = 4;
-
- so->outputs_count = 1;
- so->outputs[0].semantic =
- fd3_semantic_name(TGSI_SEMANTIC_POSITION, 0);
- so->outputs[0].regid = regid(0,0);
-
- fixup_vp_regfootprint(so);
-
- return so;
}
void
fd3_prog_init(struct pipe_context *pctx)
{
- struct fd_context *ctx = fd_context(pctx);
-
pctx->create_fs_state = fd3_fp_state_create;
- pctx->bind_fs_state = fd3_fp_state_bind;
pctx->delete_fs_state = fd3_fp_state_delete;
pctx->create_vs_state = fd3_vp_state_create;
- pctx->bind_vs_state = fd3_vp_state_bind;
pctx->delete_vs_state = fd3_vp_state_delete;
- ctx->solid_prog.fp = create_solid_fp(pctx);
- ctx->solid_prog.vp = create_solid_vp(pctx);
- ctx->blit_prog.fp = create_blit_fp(pctx);
- ctx->blit_prog.vp = create_blit_vp(pctx);
-}
-
-void
-fd3_prog_fini(struct pipe_context *pctx)
-{
- struct fd_context *ctx = fd_context(pctx);
+ fd_prog_init(pctx);
- delete_shader(ctx->solid_prog.vp);
- delete_shader(ctx->solid_prog.fp);
- delete_shader(ctx->blit_prog.vp);
- delete_shader(ctx->blit_prog.fp);
+ fix_blit_fp(pctx);
}
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_program.h b/src/gallium/drivers/freedreno/a3xx/fd3_program.h
index c781dfe4be9..a0a0de8b1ca 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_program.h
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_program.h
@@ -128,6 +128,5 @@ void fd3_program_emit(struct fd_ringbuffer *ring,
struct fd_program_stateobj *prog, bool binning);
void fd3_prog_init(struct pipe_context *pctx);
-void fd3_prog_fini(struct pipe_context *pctx);
#endif /* FD3_PROGRAM_H_ */
diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c
index 5e2e7113b2f..a8fe3111c3d 100644
--- a/src/gallium/drivers/freedreno/freedreno_context.c
+++ b/src/gallium/drivers/freedreno/freedreno_context.c
@@ -28,6 +28,7 @@
#include "freedreno_context.h"
#include "freedreno_draw.h"
+#include "freedreno_program.h"
#include "freedreno_resource.h"
#include "freedreno_texture.h"
#include "freedreno_state.h"
@@ -143,6 +144,8 @@ fd_context_destroy(struct pipe_context *pctx)
DBG("");
+ fd_prog_fini(pctx);
+
util_slab_destroy(&ctx->transfer_pool);
util_dynarray_fini(&ctx->draw_patches);
diff --git a/src/gallium/drivers/freedreno/freedreno_program.c b/src/gallium/drivers/freedreno/freedreno_program.c
new file mode 100644
index 00000000000..aaf157f3049
--- /dev/null
+++ b/src/gallium/drivers/freedreno/freedreno_program.c
@@ -0,0 +1,128 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright (C) 2014 Rob Clark <[email protected]>
+ *
+ * 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:
+ * Rob Clark <[email protected]>
+ */
+
+#include "tgsi/tgsi_text.h"
+
+#include "freedreno_program.h"
+#include "freedreno_context.h"
+
+static void
+fd_fp_state_bind(struct pipe_context *pctx, void *hwcso)
+{
+ struct fd_context *ctx = fd_context(pctx);
+ ctx->prog.fp = hwcso;
+ ctx->prog.dirty |= FD_SHADER_DIRTY_FP;
+ ctx->dirty |= FD_DIRTY_PROG;
+}
+
+static void
+fd_vp_state_bind(struct pipe_context *pctx, void *hwcso)
+{
+ struct fd_context *ctx = fd_context(pctx);
+ ctx->prog.vp = hwcso;
+ ctx->prog.dirty |= FD_SHADER_DIRTY_VP;
+ ctx->dirty |= FD_DIRTY_PROG;
+}
+
+static const char *solid_fp =
+ "FRAG \n"
+ "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1 \n"
+ "DCL CONST[0] \n"
+ "DCL OUT[0], COLOR \n"
+ " 0: MOV OUT[0], CONST[0] \n"
+ " 1: END \n";
+
+static const char *solid_vp =
+ "VERT \n"
+ "DCL IN[0] \n"
+ "DCL OUT[0], POSITION \n"
+ " 0: MOV OUT[0], IN[0] \n"
+ " 1: END \n";
+
+static const char *blit_fp =
+ "FRAG \n"
+ "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1 \n"
+ "DCL IN[0], TEXCOORD \n"
+ "DCL OUT[0], COLOR \n"
+ "DCL SAMP[0] \n"
+ " 0: TEX OUT[0], IN[0], SAMP[0], 2D \n"
+ " 1: END \n";
+
+static const char *blit_vp =
+ "VERT \n"
+ "DCL IN[0] \n"
+ "DCL IN[1] \n"
+ "DCL OUT[0], TEXCOORD \n"
+ "DCL OUT[1], POSITION \n"
+ " 0: MOV OUT[0], IN[0] \n"
+ " 0: MOV OUT[1], IN[1] \n"
+ " 1: END \n";
+
+static void * assemble_tgsi(struct pipe_context *pctx,
+ const char *src, bool frag)
+{
+ struct tgsi_token toks[32];
+ struct pipe_shader_state cso = {
+ .tokens = toks,
+ };
+
+ tgsi_text_translate(src, toks, ARRAY_SIZE(toks));
+
+ if (frag)
+ return pctx->create_fs_state(pctx, &cso);
+ else
+ return pctx->create_vs_state(pctx, &cso);
+}
+
+void fd_prog_init(struct pipe_context *pctx)
+{
+ struct fd_context *ctx = fd_context(pctx);
+
+ pctx->bind_fs_state = fd_fp_state_bind;
+ pctx->bind_vs_state = fd_vp_state_bind;
+
+ // XXX for now, let a2xx keep it's own hand-rolled shaders
+ // for solid and blit progs:
+ if (ctx->screen->gpu_id < 300)
+ return;
+
+ ctx->solid_prog.fp = assemble_tgsi(pctx, solid_fp, true);
+ ctx->solid_prog.vp = assemble_tgsi(pctx, solid_vp, false);
+ ctx->blit_prog.fp = assemble_tgsi(pctx, blit_fp, true);
+ ctx->blit_prog.vp = assemble_tgsi(pctx, blit_vp, false);
+}
+
+void fd_prog_fini(struct pipe_context *pctx)
+{
+ struct fd_context *ctx = fd_context(pctx);
+
+ pctx->delete_vs_state(pctx, ctx->solid_prog.vp);
+ pctx->delete_fs_state(pctx, ctx->solid_prog.fp);
+ pctx->delete_vs_state(pctx, ctx->blit_prog.vp);
+ pctx->delete_fs_state(pctx, ctx->blit_prog.fp);
+}
diff --git a/src/gallium/drivers/freedreno/freedreno_program.h b/src/gallium/drivers/freedreno/freedreno_program.h
new file mode 100644
index 00000000000..37efe1bcf4d
--- /dev/null
+++ b/src/gallium/drivers/freedreno/freedreno_program.h
@@ -0,0 +1,37 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright (C) 2014 Rob Clark <[email protected]>
+ *
+ * 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:
+ * Rob Clark <[email protected]>
+ */
+
+#ifndef FREEDRENO_PROGRAM_H_
+#define FREEDRENO_PROGRAM_H_
+
+#include "pipe/p_context.h"
+
+void fd_prog_init(struct pipe_context *pctx);
+void fd_prog_fini(struct pipe_context *pctx);
+
+#endif /* FREEDRENO_PROGRAM_H_ */