]> git.tdb.fi Git - libs/gl.git/blob - source/core/pipelinestate.cpp
Check the flat qualifier from the correct member
[libs/gl.git] / source / core / pipelinestate.cpp
1 #include <stdexcept>
2 #include <msp/core/algorithm.h>
3 #include <msp/io/print.h>
4 #include "error.h"
5 #include "pipelinestate.h"
6 #include "program.h"
7 #include "uniformblock.h"
8
9 using namespace std;
10
11 namespace Msp {
12 namespace GL {
13
14 template<typename T>
15 void PipelineState::set(T &target, const T &value, unsigned flag)
16 {
17         if(value!=target)
18         {
19                 target = value;
20                 changes |= flag;
21         }
22 }
23
24 void PipelineState::set_framebuffer(const Framebuffer *f)
25 {
26         set(framebuffer, f, FRAMEBUFFER);
27 }
28
29 void PipelineState::set_viewport(const Rect &v)
30 {
31         set(viewport, v, VIEWPORT);
32 }
33
34 void PipelineState::set_scissor(const Rect &s)
35 {
36         set(scissor, s, SCISSOR);
37 }
38
39 void PipelineState::set_shader_program(const Program *p)
40 {
41         set(shprog, p, SHPROG);
42 }
43
44 void PipelineState::set_uniform_block(int binding, const UniformBlock *block)
45 {
46         auto i = lower_bound_member(resources, binding, &BoundResource::binding);
47         if(i==resources.end() || i->binding!=binding)
48                 i = resources.insert(i, BoundResource(binding));
49
50         ResourceType type = (block ? UNIFORM_BLOCK : NO_RESOURCE);
51         const Buffer *buffer = (block ? block->get_buffer() : 0);
52         if(i->type!=type || block!=i->block || buffer!=i->buffer || binding<0)
53         {
54                 i->type = type;
55                 i->block = block;
56                 i->buffer = buffer;
57                 i->changed = true;
58                 i->used = block;
59                 changes |= RESOURCES;
60         }
61 }
62
63 void PipelineState::set_texture(unsigned binding, const Texture *tex, const Sampler *samp)
64 {
65         set_texture(binding, tex, -1, samp);
66 }
67
68 void PipelineState::set_texture(unsigned binding, const Texture *tex, int level, const Sampler *samp)
69 {
70         if((tex!=0)!=(samp!=0))
71                 throw invalid_argument("PipelineState::set_texture");
72         if(level>=0 && !can_bind_tex_level(level))
73                 throw invalid_operation("PipelineState::set_texture");
74
75         set_texture_resource(binding, tex, level, samp);
76 }
77
78 void PipelineState::set_storage_texture(unsigned binding, const Texture *tex)
79 {
80         set_texture_resource(binding, tex, 0, 0);
81 }
82
83 void PipelineState::set_texture_resource(unsigned binding, const Texture *tex, int level, const Sampler *samp)
84 {
85         auto i = lower_bound_member(resources, static_cast<int>(binding), &BoundResource::binding);
86         if(i==resources.end() || i->binding!=static_cast<int>(binding))
87                 i = resources.insert(i, BoundResource(binding));
88
89         ResourceType type = (tex ? samp ? SAMPLED_TEXTURE : STORAGE_TEXTURE : NO_RESOURCE);
90         if(i->type!=type || tex!=i->texture || level!=i->mip_level || samp!=i->sampler)
91         {
92                 i->type = type;
93                 i->texture = tex;
94                 i->sampler = samp;
95                 i->mip_level = level;
96                 i->changed = true;
97                 i->used = tex;
98                 changes |= RESOURCES;
99         }
100 }
101
102 void PipelineState::set_vertex_setup(const VertexSetup *s)
103 {
104         set(vertex_setup, s, VERTEX_SETUP);
105 }
106
107 void PipelineState::set_primitive_type(PrimitiveType t)
108 {
109         set(primitive_type, t, PRIMITIVE_TYPE);
110 }
111
112 void PipelineState::set_patch_size(unsigned s)
113 {
114         set(patch_size, s, PATCH_SIZE);
115 }
116
117 void PipelineState::set_front_face(FaceWinding w)
118 {
119         set(front_face, w, FACE_CULL);
120 }
121
122 void PipelineState::set_face_cull(CullMode c)
123 {
124         set(face_cull, c, FACE_CULL);
125 }
126
127 void PipelineState::set_depth_test(const DepthTest &dt)
128 {
129         set(depth_test, dt, DEPTH_TEST);
130 }
131
132 void PipelineState::set_stencil_test(const StencilTest &st)
133 {
134         set(stencil_test, st, STENCIL_TEST);
135 }
136
137 void PipelineState::set_blend(const Blend &b)
138 {
139         set(blend, b, BLEND);
140 }
141
142 void PipelineState::check_bound_resources() const
143 {
144         if(!shprog)
145                 return;
146
147         for(const ReflectData::UniformBlockInfo &b: shprog->get_uniform_blocks())
148                 if(b.bind_point!=ReflectData::DEFAULT_BLOCK)
149                 {
150                         auto i = lower_bound_member(resources, b.bind_point, &PipelineState::BoundResource::binding);
151                         if(i==resources.end() || i->binding!=b.bind_point)
152                                 IO::print(IO::cerr, "Warning: No resource present for uniform block binding %d:%d (%s)\n", b.bind_point>>20, b.bind_point&0xFFFFF, b.name);
153                 }
154
155         for(const ReflectData::UniformInfo &u: shprog->get_uniforms())
156                 if(u.binding>=0 && is_image(u.type))
157                 {
158                         auto i = lower_bound_member(resources, u.binding, &PipelineState::BoundResource::binding);
159                         if(i==resources.end() || i->binding!=u.binding)
160                                 IO::print(IO::cerr, "Warning: No resource present for texture binding %d:%d (%s)\n", u.binding>>20, u.binding&0xFFFFF, u.name);
161                 }
162 }
163
164 } // namespace GL
165 } // namespace Msp