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
;
40 struct pipe_transfer
*transfer
;
44 if (unlikely(!fp
->buffer
)) {
45 fp
->buffer
= pipe_buffer_create(pipe
->screen
, 0, 0, fp
->insn_len
* 4);
48 map
= pipe_buffer_map(pipe
, fp
->buffer
, PIPE_TRANSFER_WRITE
, &transfer
);
49 #ifndef PIPE_ARCH_BIG_ENDIAN
50 memcpy(map
, fp
->insn
, fp
->insn_len
* 4);
52 for (i
= 0; i
< fp
->insn_len
; i
++)
53 *map
++ = (fp
->insn
[i
] >> 16) | (fp
->insn
[i
] << 16);
55 pipe_buffer_unmap(pipe
, transfer
);
57 if (nv04_resource(fp
->buffer
)->domain
!= NOUVEAU_BO_VRAM
)
58 nouveau_buffer_migrate(nv
, nv04_resource(fp
->buffer
), NOUVEAU_BO_VRAM
);
62 nv30_fragprog_validate(struct nv30_context
*nv30
)
64 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
65 struct nouveau_object
*eng3d
= nv30
->screen
->eng3d
;
66 struct nv30_fragprog
*fp
= nv30
->fragprog
.program
;
67 boolean upload
= FALSE
;
70 if (!fp
->translated
) {
71 _nvfx_fragprog_translate(eng3d
->oclass
, fp
);
78 /* update constants, also needs to be done on every fp switch as we
79 * have no idea whether the constbuf changed in the meantime
81 if (nv30
->fragprog
.constbuf
) {
82 struct pipe_resource
*constbuf
= nv30
->fragprog
.constbuf
;
83 uint32_t *cbuf
= (uint32_t *)nv04_resource(constbuf
)->data
;
85 for (i
= 0; i
< fp
->nr_consts
; i
++) {
86 unsigned off
= fp
->consts
[i
].offset
;
87 unsigned idx
= fp
->consts
[i
].index
* 4;
89 if (!memcmp(&fp
->insn
[off
], &cbuf
[idx
], 4 * 4))
91 memcpy(&fp
->insn
[off
], &cbuf
[idx
], 4 * 4);
97 nv30_fragprog_upload(nv30
);
99 /* FP_ACTIVE_PROGRAM needs to be done again even if only the consts
100 * were updated. TEX_CACHE_CTL magic is not enough to convince the
101 * GPU that it should re-read the fragprog from VRAM... sigh.
103 if (nv30
->state
.fragprog
!= fp
|| upload
) {
104 struct nv04_resource
*r
= nv04_resource(fp
->buffer
);
106 if (!PUSH_SPACE(push
, 8))
108 PUSH_RESET(push
, BUFCTX_FRAGPROG
);
110 BEGIN_NV04(push
, NV30_3D(FP_ACTIVE_PROGRAM
), 1);
111 PUSH_RESRC(push
, NV30_3D(FP_ACTIVE_PROGRAM
), BUFCTX_FRAGPROG
, r
, 0,
112 NOUVEAU_BO_LOW
| NOUVEAU_BO_RD
| NOUVEAU_BO_OR
,
113 NV30_3D_FP_ACTIVE_PROGRAM_DMA0
,
114 NV30_3D_FP_ACTIVE_PROGRAM_DMA1
);
115 BEGIN_NV04(push
, NV30_3D(FP_CONTROL
), 1);
116 PUSH_DATA (push
, fp
->fp_control
);
117 if (eng3d
->oclass
< NV40_3D_CLASS
) {
118 BEGIN_NV04(push
, NV30_3D(FP_REG_CONTROL
), 1);
119 PUSH_DATA (push
, 0x00010004);
120 BEGIN_NV04(push
, NV30_3D(TEX_UNITS_ENABLE
), 1);
121 PUSH_DATA (push
, fp
->texcoords
);
123 BEGIN_NV04(push
, SUBC_3D(0x0b40), 1);
124 PUSH_DATA (push
, 0x00000000);
127 nv30
->state
.fragprog
= fp
;
132 nv30_fp_state_create(struct pipe_context
*pipe
,
133 const struct pipe_shader_state
*cso
)
135 struct nv30_fragprog
*fp
= CALLOC_STRUCT(nv30_fragprog
);
139 fp
->pipe
.tokens
= tgsi_dup_tokens(cso
->tokens
);
140 tgsi_scan_shader(fp
->pipe
.tokens
, &fp
->info
);
145 nv30_fp_state_delete(struct pipe_context
*pipe
, void *hwcso
)
147 struct nv30_fragprog
*fp
= hwcso
;
149 pipe_resource_reference(&fp
->buffer
, NULL
);
152 draw_delete_fragment_shader(nv30_context(pipe
)->draw
, fp
->draw
);
154 FREE((void *)fp
->pipe
.tokens
);
161 nv30_fp_state_bind(struct pipe_context
*pipe
, void *hwcso
)
163 struct nv30_context
*nv30
= nv30_context(pipe
);
165 nv30
->fragprog
.program
= hwcso
;
166 nv30
->dirty
|= NV30_NEW_FRAGPROG
;
170 nv30_fragprog_init(struct pipe_context
*pipe
)
172 pipe
->create_fs_state
= nv30_fp_state_create
;
173 pipe
->bind_fs_state
= nv30_fp_state_bind
;
174 pipe
->delete_fs_state
= nv30_fp_state_delete
;