2 * Copyright 2012 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "draw/draw_context.h"
27 #include "tgsi/tgsi_parse.h"
29 #include "nv_object.xml.h"
30 #include "nv30/nv30-40_3d.xml.h"
31 #include "nv30/nv30_context.h"
32 #include "nv30/nvfx_shader.h"
35 nv30_fragprog_upload(struct nv30_context
*nv30
)
37 struct nouveau_context
*nv
= &nv30
->base
;
38 struct nv30_fragprog
*fp
= nv30
->fragprog
.program
;
39 struct pipe_context
*pipe
= &nv30
->base
.pipe
;
41 if (unlikely(!fp
->buffer
))
42 fp
->buffer
= pipe_buffer_create(pipe
->screen
, 0, 0, fp
->insn_len
* 4);
44 #if !PIPE_ARCH_BIG_ENDIAN
45 pipe_buffer_write(pipe
, fp
->buffer
, 0, fp
->insn_len
* 4, fp
->insn
);
48 struct pipe_transfer
*transfer
;
52 map
= pipe_buffer_map(pipe
, fp
->buffer
,
53 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE
,
55 for (i
= 0; i
< fp
->insn_len
; i
++)
56 *map
++ = (fp
->insn
[i
] >> 16) | (fp
->insn
[i
] << 16);
57 pipe_buffer_unmap(pipe
, transfer
);
61 if (nv04_resource(fp
->buffer
)->domain
!= NOUVEAU_BO_VRAM
)
62 nouveau_buffer_migrate(nv
, nv04_resource(fp
->buffer
), NOUVEAU_BO_VRAM
);
66 nv30_fragprog_validate(struct nv30_context
*nv30
)
68 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
69 struct nouveau_object
*eng3d
= nv30
->screen
->eng3d
;
70 struct nv30_fragprog
*fp
= nv30
->fragprog
.program
;
74 if (!fp
->translated
) {
75 _nvfx_fragprog_translate(eng3d
->oclass
, fp
);
82 /* update constants, also needs to be done on every fp switch as we
83 * have no idea whether the constbuf changed in the meantime
85 if (nv30
->fragprog
.constbuf
) {
86 struct pipe_resource
*constbuf
= nv30
->fragprog
.constbuf
;
87 uint32_t *cbuf
= (uint32_t *)nv04_resource(constbuf
)->data
;
89 for (i
= 0; i
< fp
->nr_consts
; i
++) {
90 unsigned off
= fp
->consts
[i
].offset
;
91 unsigned idx
= fp
->consts
[i
].index
* 4;
93 if (!memcmp(&fp
->insn
[off
], &cbuf
[idx
], 4 * 4))
95 memcpy(&fp
->insn
[off
], &cbuf
[idx
], 4 * 4);
101 nv30_fragprog_upload(nv30
);
103 /* FP_ACTIVE_PROGRAM needs to be done again even if only the consts
104 * were updated. TEX_CACHE_CTL magic is not enough to convince the
105 * GPU that it should re-read the fragprog from VRAM... sigh.
107 if (nv30
->state
.fragprog
!= fp
|| upload
) {
108 struct nv04_resource
*r
= nv04_resource(fp
->buffer
);
110 if (!PUSH_SPACE(push
, 8))
112 PUSH_RESET(push
, BUFCTX_FRAGPROG
);
114 BEGIN_NV04(push
, NV30_3D(FP_ACTIVE_PROGRAM
), 1);
115 PUSH_RESRC(push
, NV30_3D(FP_ACTIVE_PROGRAM
), BUFCTX_FRAGPROG
, r
, 0,
116 NOUVEAU_BO_LOW
| NOUVEAU_BO_RD
| NOUVEAU_BO_OR
,
117 NV30_3D_FP_ACTIVE_PROGRAM_DMA0
,
118 NV30_3D_FP_ACTIVE_PROGRAM_DMA1
);
119 BEGIN_NV04(push
, NV30_3D(FP_CONTROL
), 1);
120 PUSH_DATA (push
, fp
->fp_control
);
121 if (eng3d
->oclass
< NV40_3D_CLASS
) {
122 BEGIN_NV04(push
, NV30_3D(FP_REG_CONTROL
), 1);
123 PUSH_DATA (push
, 0x00010004);
124 BEGIN_NV04(push
, NV30_3D(TEX_UNITS_ENABLE
), 1);
125 PUSH_DATA (push
, fp
->texcoords
);
127 BEGIN_NV04(push
, SUBC_3D(0x0b40), 1);
128 PUSH_DATA (push
, 0x00000000);
131 nv30
->state
.fragprog
= fp
;
136 nv30_fp_state_create(struct pipe_context
*pipe
,
137 const struct pipe_shader_state
*cso
)
139 struct nv30_fragprog
*fp
= CALLOC_STRUCT(nv30_fragprog
);
143 fp
->pipe
.tokens
= tgsi_dup_tokens(cso
->tokens
);
144 tgsi_scan_shader(fp
->pipe
.tokens
, &fp
->info
);
149 nv30_fp_state_delete(struct pipe_context
*pipe
, void *hwcso
)
151 struct nv30_fragprog
*fp
= hwcso
;
153 pipe_resource_reference(&fp
->buffer
, NULL
);
156 draw_delete_fragment_shader(nv30_context(pipe
)->draw
, fp
->draw
);
158 FREE((void *)fp
->pipe
.tokens
);
165 nv30_fp_state_bind(struct pipe_context
*pipe
, void *hwcso
)
167 struct nv30_context
*nv30
= nv30_context(pipe
);
168 struct nv30_fragprog
*fp
= hwcso
;
170 /* reset the bucftx so that we don't keep a dangling reference to the fp
173 if (fp
!= nv30
->state
.fragprog
)
174 nouveau_bufctx_reset(nv30
->bufctx
, BUFCTX_FRAGPROG
);
176 nv30
->fragprog
.program
= fp
;
177 nv30
->dirty
|= NV30_NEW_FRAGPROG
;
181 nv30_fragprog_init(struct pipe_context
*pipe
)
183 pipe
->create_fs_state
= nv30_fp_state_create
;
184 pipe
->bind_fs_state
= nv30_fp_state_bind
;
185 pipe
->delete_fs_state
= nv30_fp_state_delete
;