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 "tgsi/tgsi_parse.h"
28 #include "nv_object.xml.h"
29 #include "nv30/nv30-40_3d.xml.h"
30 #include "nv30/nv30_context.h"
31 #include "nv30/nvfx_shader.h"
34 nv30_fragprog_upload(struct nv30_context
*nv30
)
36 struct nouveau_context
*nv
= &nv30
->base
;
37 struct nv30_fragprog
*fp
= nv30
->fragprog
.program
;
38 struct pipe_context
*pipe
= &nv30
->base
.pipe
;
39 struct pipe_transfer
*transfer
;
43 if (unlikely(!fp
->buffer
)) {
44 fp
->buffer
= pipe_buffer_create(pipe
->screen
, 0, 0, fp
->insn_len
* 4);
47 map
= pipe_buffer_map(pipe
, fp
->buffer
, PIPE_TRANSFER_WRITE
, &transfer
);
48 #ifndef PIPE_ARCH_BIG_ENDIAN
49 memcpy(map
, fp
->insn
, fp
->insn_len
* 4);
51 for (i
= 0; i
< fp
->insn_len
; i
++)
52 *map
++ = (fp
->insn
[i
] >> 16) | (fp
->insn
[i
] << 16);
54 pipe_buffer_unmap(pipe
, transfer
);
56 if (nv04_resource(fp
->buffer
)->domain
!= NOUVEAU_BO_VRAM
)
57 nouveau_buffer_migrate(nv
, nv04_resource(fp
->buffer
), NOUVEAU_BO_VRAM
);
61 nv30_fragprog_validate(struct nv30_context
*nv30
)
63 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
64 struct nouveau_object
*eng3d
= nv30
->screen
->eng3d
;
65 struct nv30_fragprog
*fp
= nv30
->fragprog
.program
;
66 boolean upload
= FALSE
;
69 if (!fp
->translated
) {
70 _nvfx_fragprog_translate(eng3d
->oclass
, fp
);
77 /* update constants, also needs to be done on every fp switch as we
78 * have no idea whether the constbuf changed in the meantime
80 if (nv30
->fragprog
.constbuf
) {
81 struct pipe_resource
*constbuf
= nv30
->fragprog
.constbuf
;
82 uint32_t *cbuf
= (uint32_t *)nv04_resource(constbuf
)->data
;
84 for (i
= 0; i
< fp
->nr_consts
; i
++) {
85 unsigned off
= fp
->consts
[i
].offset
;
86 unsigned idx
= fp
->consts
[i
].index
* 4;
88 if (!memcmp(&fp
->insn
[off
], &cbuf
[idx
], 4 * 4))
90 memcpy(&fp
->insn
[off
], &cbuf
[idx
], 4 * 4);
96 nv30_fragprog_upload(nv30
);
98 /* FP_ACTIVE_PROGRAM needs to be done again even if only the consts
99 * were updated. TEX_CACHE_CTL magic is not enough to convince the
100 * GPU that it should re-read the fragprog from VRAM... sigh.
102 if (nv30
->state
.fragprog
!= fp
|| upload
) {
103 struct nv04_resource
*r
= nv04_resource(fp
->buffer
);
105 if (!PUSH_SPACE(push
, 8))
107 PUSH_RESET(push
, BUFCTX_FRAGPROG
);
109 BEGIN_NV04(push
, NV30_3D(FP_ACTIVE_PROGRAM
), 1);
110 PUSH_RESRC(push
, NV30_3D(FP_ACTIVE_PROGRAM
), BUFCTX_FRAGPROG
, r
, 0,
111 NOUVEAU_BO_LOW
| NOUVEAU_BO_RD
| NOUVEAU_BO_OR
,
112 NV30_3D_FP_ACTIVE_PROGRAM_DMA0
,
113 NV30_3D_FP_ACTIVE_PROGRAM_DMA1
);
114 BEGIN_NV04(push
, NV30_3D(FP_CONTROL
), 1);
115 PUSH_DATA (push
, fp
->fp_control
);
116 if (eng3d
->oclass
< NV40_3D_CLASS
) {
117 BEGIN_NV04(push
, NV30_3D(FP_REG_CONTROL
), 1);
118 PUSH_DATA (push
, 0x00010004);
119 BEGIN_NV04(push
, NV30_3D(TEX_UNITS_ENABLE
), 1);
120 PUSH_DATA (push
, fp
->texcoords
);
122 BEGIN_NV04(push
, SUBC_3D(0x0b40), 1);
123 PUSH_DATA (push
, 0x00000000);
126 nv30
->state
.fragprog
= fp
;
131 nv30_fp_state_create(struct pipe_context
*pipe
,
132 const struct pipe_shader_state
*cso
)
134 struct nv30_fragprog
*fp
= CALLOC_STRUCT(nv30_fragprog
);
138 fp
->pipe
.tokens
= tgsi_dup_tokens(cso
->tokens
);
139 tgsi_scan_shader(fp
->pipe
.tokens
, &fp
->info
);
144 nv30_fp_state_delete(struct pipe_context
*pipe
, void *hwcso
)
146 struct nv30_fragprog
*fp
= hwcso
;
148 pipe_resource_reference(&fp
->buffer
, NULL
);
150 FREE((void *)fp
->pipe
.tokens
);
157 nv30_fp_state_bind(struct pipe_context
*pipe
, void *hwcso
)
159 struct nv30_context
*nv30
= nv30_context(pipe
);
161 nv30
->fragprog
.program
= hwcso
;
162 nv30
->dirty
|= NV30_NEW_FRAGPROG
;
166 nv30_fragprog_init(struct pipe_context
*pipe
)
168 pipe
->create_fs_state
= nv30_fp_state_create
;
169 pipe
->bind_fs_state
= nv30_fp_state_bind
;
170 pipe
->delete_fs_state
= nv30_fp_state_delete
;