25 #include "base/integral_types.h"
66 using base::DataContainer;
74 static const GLuint kInvalidGluint =
static_cast<GLuint
>(-1);
85 static base::ReadWriteLock* GetResourceBinderLock() {
94 GLuint* stride, GLuint* slots) {
99 *stride =
static_cast<GLuint
>(2U *
sizeof(float));
103 *stride =
static_cast<GLuint
>(3U *
sizeof(float));
107 *stride =
static_cast<GLuint
>(4U *
sizeof(float));
116 static GLuint GetAttributeSlotCountByGlType(GLenum type) {
135 static const char* GetShaderTypeString(GLenum shader_type) {
136 const char* type =
"<UNKNOWN>";
137 if (shader_type == GL_VERTEX_SHADER)
139 else if (shader_type == GL_FRAGMENT_SHADER)
145 static void SetObjectLabel(GraphicsManager* gm, GLenum type, GLuint
id,
146 const std::string&
label) {
149 gm->LabelObject(type,
id, static_cast<GLsizei>(label.length()),
155 static bool ValidateUniformType(
const char*
name,
158 bool types_equal =
false;
161 types_equal = type == GL_INT;
164 types_equal = type == GL_FLOAT;
167 types_equal = type == GL_UNSIGNED_INT;
170 types_equal = type == GL_INT_SAMPLER_CUBE ||
171 type == GL_INT_SAMPLER_CUBE_MAP_ARRAY ||
172 type == GL_SAMPLER_CUBE ||
173 type == GL_SAMPLER_CUBE_MAP_ARRAY ||
174 type == GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW ||
175 type == GL_SAMPLER_CUBE_SHADOW ||
176 type == GL_UNSIGNED_INT_SAMPLER_CUBE ||
177 type == GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY;
181 type == GL_INT_SAMPLER_1D || type == GL_INT_SAMPLER_1D_ARRAY ||
182 type == GL_INT_SAMPLER_2D || type == GL_INT_SAMPLER_2D_ARRAY ||
183 type == GL_INT_SAMPLER_3D || type == GL_SAMPLER_1D ||
184 type == GL_SAMPLER_1D_ARRAY || type == GL_SAMPLER_1D_ARRAY_SHADOW ||
185 type == GL_SAMPLER_1D_SHADOW || type == GL_SAMPLER_2D ||
186 type == GL_SAMPLER_2D_ARRAY || type == GL_SAMPLER_2D_ARRAY_SHADOW ||
187 type == GL_SAMPLER_2D_MULTISAMPLE ||
188 type == GL_SAMPLER_2D_MULTISAMPLE_ARRAY ||
189 type == GL_SAMPLER_2D_SHADOW || type == GL_SAMPLER_3D ||
191 type == GL_UNSIGNED_INT_SAMPLER_1D ||
192 type == GL_UNSIGNED_INT_SAMPLER_1D_ARRAY ||
193 type == GL_UNSIGNED_INT_SAMPLER_2D ||
194 type == GL_UNSIGNED_INT_SAMPLER_2D_ARRAY ||
195 type == GL_UNSIGNED_INT_SAMPLER_3D;
198 types_equal = type == GL_FLOAT_VEC2;
201 types_equal = type == GL_FLOAT_VEC3;
204 types_equal = type == GL_FLOAT_VEC4;
207 types_equal = type == GL_INT_VEC2;
210 types_equal = type == GL_INT_VEC3;
213 types_equal = type == GL_INT_VEC4;
216 types_equal = type == GL_FLOAT_MAT2;
219 types_equal = type == GL_FLOAT_MAT3;
222 types_equal = type == GL_FLOAT_MAT4;
225 types_equal = type == GL_UNSIGNED_INT_VEC2;
228 types_equal = type == GL_UNSIGNED_INT_VEC3;
231 types_equal = type == GL_UNSIGNED_INT_VEC4;
233 #if !defined(ION_COVERAGE) // COV_NF_START
245 static GLuint CompileShader(
const std::string& id_string, GLenum shader_type,
246 const std::string& source, std::string* info_log,
247 GraphicsManager* gm) {
251 GLuint
id = gm->CreateShader(shader_type);
255 const char* source_string = source.c_str();
256 gm->ShaderSource(
id, 1, &source_string,
nullptr);
257 gm->CompileShader(
id);
261 gm->GetShaderiv(
id, GL_COMPILE_STATUS, &ok);
265 gm->GetShaderInfoLog(
id, 2047,
nullptr, log);
267 LOG(
ERROR) <<
"***ION: Unable to compile "
268 << GetShaderTypeString(shader_type) <<
" shader for '"
269 << id_string <<
"': " << log;
270 gm->DeleteShader(
id);
274 LOG(
ERROR) <<
"***ION: Unable to create shader object";
281 static GLuint RelinkShaderProgram(
const std::string& id_string,
282 GLuint program_id, GLuint vertex_shader_id,
283 GLuint fragment_shader_id,
284 std::string* info_log, GraphicsManager* gm) {
289 gm->LinkProgram(program_id);
293 gm->GetProgramiv(program_id, GL_LINK_STATUS, &ok);
297 gm->GetProgramInfoLog(program_id, 2047,
nullptr, log);
299 LOG(
ERROR) <<
"***ION: Unable to link shader program for '" << id_string
301 gm->DeleteProgram(program_id);
310 static GLuint LinkShaderProgram(
const std::string& id_string,
311 GLuint vertex_shader_id,
312 GLuint fragment_shader_id,
313 std::string* info_log, GraphicsManager* gm) {
314 GLuint program_id = gm->CreateProgram();
316 if (vertex_shader_id)
317 gm->AttachShader(program_id, vertex_shader_id);
318 if (fragment_shader_id)
319 gm->AttachShader(program_id, fragment_shader_id);
321 program_id = RelinkShaderProgram(id_string, program_id, vertex_shader_id,
322 fragment_shader_id, info_log, gm);
324 LOG(
ERROR) <<
"***ION: Unable to create shader program object";
332 const ImagePtr GetCubeMapTextureImageOrMipmap(
const CubeMapTexture& tex,
335 const size_t mipmap_count = tex.GetImageCount(face);
336 for (
size_t i = 0; i < mipmap_count; ++i) {
337 if (tex.HasImage(face, i))
338 return tex.GetImage(face, i);
342 const ImagePtr GetTextureImageOrMipmap(
const Texture& tex) {
345 const size_t mipmap_count = tex.GetImageCount();
346 for (
size_t i = 0; i < mipmap_count; ++i) {
347 if (tex.HasImage(i)) {
348 image = tex.GetImage(i);
356 class AttributeArrayEmulator :
public AttributeArray {
358 AttributeArrayEmulator() {}
359 ~AttributeArrayEmulator()
override {}
364 static Image::PixelFormat GetCompatiblePixelFormat(Image::PixelFormat pf,
365 GraphicsManager* gm) {
367 if (gm->GetGlVersion() >= 30 &&
371 pf.internal_format = GL_R8;
375 pf.internal_format = GL_RG8;
378 }
else if (gm->GetGlVersion() < 30) {
380 if (pf.format == GL_RED) {
383 }
else if (pf.format == GL_RG) {
394 typedef void (GraphicsManager::*UniformMatrixSetter)(
395 GLint, GLsizei, GLboolean,
const GLfloat*);
397 template <
int Dimension>
398 inline static void SendMatrixUniform(
const Uniform& uniform,
401 UniformMatrixSetter setter) {
402 typedef math::Matrix<Dimension, float> Matrix;
403 if (uniform.IsArrayOf<Matrix>()) {
405 const GLint count =
static_cast<GLint
>(uniform.GetCount());
409 Matrix* mats =
static_cast<Matrix*
>(allocator->AllocateMemory(
410 sizeof(Matrix) * count));
411 for (GLint i = 0; i < count; ++i)
413 (gm->*setter)(location, count, GL_FALSE, reinterpret_cast<float*>(mats));
414 allocator->DeallocateMemory(mats);
416 (gm->*setter)(location, 1, GL_FALSE,
432 template <
typename T>
433 struct Renderer::HolderToResource {};
437 struct Renderer::HolderToResource<AttributeArray> {
441 struct Renderer::HolderToResource<AttributeArrayEmulator> {
442 typedef Renderer::VertexArrayEmulatorResource
ResourceType;
445 struct Renderer::HolderToResource<BufferObject> {
449 struct Renderer::HolderToResource<CubeMapTexture> {
453 struct Renderer::HolderToResource<FramebufferObject> {
457 struct Renderer::HolderToResource<IndexBuffer> {
461 struct Renderer::HolderToResource<Sampler> {
465 struct Renderer::HolderToResource<Shader> {
469 struct Renderer::HolderToResource<ShaderProgram> {
473 struct Renderer::HolderToResource<ShaderInputRegistry> {
474 typedef Renderer::ShaderInputRegistryResource
ResourceType;
477 struct Renderer::HolderToResource<TextureBase> {
481 struct Renderer::HolderToResource<Texture> {
495 class Renderer::ResourceManager :
public gfx::ResourceManager {
499 class Resource :
public ResourceBase,
public Allocatable {
505 size_t GetGpuMemoryUsed()
const override {
return gpu_memory_used_.load(); }
508 explicit Resource(ResourceManager* rm,
const ResourceHolder* holder,
512 resource_manager_(rm),
513 gpu_memory_used_(0U) {}
517 virtual void Release(
bool can_make_gl_calls) = 0;
518 virtual void Update(ResourceBinder* rb) = 0;
519 virtual void Unbind(ResourceBinder* rb) = 0;
524 void SetUsedGpuMemory(
size_t count) {
528 const size_t old_used = gpu_memory_used_.load();
529 resource_manager_->IncreaseGpuMemoryUsage(type, count);
530 resource_manager_->DecreaseGpuMemoryUsage(type, old_used);
533 if (resource_manager_->GetAllocator().Get() &&
534 resource_manager_->GetAllocator()->GetTracker().Get() &&
535 resource_manager_->GetAllocator()
540 resource_manager_->GetAllocator()->GetTracker()->GetGpuTracker();
541 UpdateAllocationSizeTracker(global_gpu_tracker, count, old_used);
549 UpdateAllocationSizeTracker(gpu_tracker, count, old_used);
551 gpu_memory_used_ = count;
557 template <
typename HolderType>
558 typename HolderToResource<HolderType>::ResourceType* GetResource(
559 const HolderType* holder, ResourceBinder* binder, GLuint gl_id = 0) {
560 DCHECK(resource_manager_);
561 return resource_manager_->GetResource(holder, binder, gl_id);
566 base::ReadLock read_lock(GetResourceBinderLock());
568 ResourceBinderMap& binders = GetResourceBinderMap();
569 for (ResourceBinderMap::iterator it = binders.begin();
572 Unbind(it->second.get());
576 void SetIndex(
size_t index) { index_ = index; }
577 size_t GetIndex()
const {
return index_; }
581 void UpdateAllocationSizeTracker(
584 if (count) tracker->TrackAllocationSize(count);
585 if (old_used) tracker->TrackDeallocationSize(old_used);
593 ResourceManager* resource_manager_;
596 std::atomic<size_t> gpu_memory_used_;
598 friend class ResourceBinder;
599 friend class Renderer::ResourceManager;
602 typedef base::AllocVector<Resource*> ResourceVector;
604 class ResourceAccessor;
609 ResourceContainer() : resources_(*this) {}
612 friend class ResourceAccessor;
614 ResourceVector resources_;
620 class ResourceAccessor {
622 explicit ResourceAccessor(ResourceContainer& container)
623 : container_(container),
625 container_.mutex_.Lock();
630 ResourceAccessor(ResourceAccessor& other)
631 : container_(other.container_),
633 other.owns_lock_ =
false;
635 ~ResourceAccessor() {
637 container_.mutex_.Unlock();
641 ResourceVector& GetResources() {
return container_.resources_; }
644 ResourceContainer& container_;
653 resource_index_(AcquireOrReleaseResourceIndex(false, 0U)),
654 memory_usage_(*this),
655 resources_to_release_(*this) {
657 ResourceAccessor(resources_[
kAttributeArray]).GetResources().reserve(128U);
658 ResourceAccessor(resources_[
kBufferObject]).GetResources().reserve(128U);
661 ResourceAccessor(resources_[
kSampler]).GetResources().reserve(32U);
664 ResourceAccessor(resources_[
kShaderProgram]).GetResources().reserve(16U);
665 ResourceAccessor(resources_[
kShader]).GetResources().reserve(16U);
666 ResourceAccessor(resources_[
kTexture]).GetResources().reserve(128U);
674 size_t GetResourceIndex()
const {
return resource_index_; }
678 ResourceAccessor accessor(resources_[type]);
687 template <
typename T>
688 ResourceKey GetResourceKey(ResourceBinder* resource_binder,
689 const ResourceHolder* holder) {
697 template <
typename T>
698 std::vector<ResourceKey> GetAllResourceKeys(ResourceBinder* resource_binder) {
699 std::vector<ResourceKey> keys;
700 keys.push_back(GetResourceKey<T>(resource_binder,
nullptr));
705 template <
typename HolderType>
706 typename HolderToResource<HolderType>::ResourceType* GetResource(
707 const HolderType* holder, ResourceBinder* resource_binder,
711 void IncreaseGpuMemoryUsage(
ResourceType type,
size_t count) {
712 memory_usage_[
type].value += count;
716 void DecreaseGpuMemoryUsage(
ResourceType type,
size_t count) {
718 memory_usage_[
type].value -= count;
723 return memory_usage_[
type].value.load();
729 void DisassociateElementBufferFromArrays(BufferResource* resource);
732 void AddResource(Resource* resource) {
733 ResourceAccessor accessor(resources_[resource->GetType()]);
734 ResourceVector& resources = accessor.GetResources();
735 resource->SetIndex(resources.size());
736 resources.push_back(resource);
740 void MarkForRelease(Resource* resource) {
743 resources_to_release_.push_back(resource);
747 void DestroyResource(Resource* resource) {
752 ResourceAccessor accessor(resources_[resource->GetType()]);
753 ResourceVector& resources = accessor.GetResources();
754 const size_t num_resources = resources.size();
755 if (num_resources > 1U) {
756 const size_t index = resource->GetIndex();
759 if (resources[index] == resource) {
760 Resource* moved_resource = resources[num_resources - 1U];
761 resources[index] = moved_resource;
762 moved_resource->SetIndex(index);
763 resources.resize(num_resources - 1U);
765 }
else if (num_resources == 1U) {
767 if (resources[0] == resource)
774 template <
typename HolderType>
776 typedef typename HolderToResource<HolderType>::ResourceType
ResourceType;
778 const std::vector<ResourceKey> keys =
779 GetAllResourceKeys<ResourceType>(binder);
781 if (ResourceBase* resource =
782 holder->GetResource(resource_index_, key)) {
783 resource->OnDestroyed();
791 void ReleaseTypedResources(ResourceType type) {
792 ResourceAccessor accessor(resources_[type]);
793 ResourceVector& resources = accessor.GetResources();
794 for (
auto resource : resources) {
795 resource->OnDestroyed();
800 void ReleaseAll(ResourceBinder* resource_binder) {
806 ResourceVector resources_to_destroy(*
this);
809 for (Resource* resource : resources_to_release_) {
810 resource->Release(can_make_gl_calls);
812 resources_to_destroy.push_back(resource);
813 DestroyResource(resource);
815 resources_to_release_.clear();
824 for (Resource* resource : resources_to_destroy)
831 if (resources_to_release_.empty())
838 void DestroyAllResources() {
841 ResourceAccessor accessor(resources_[i]);
842 ResourceVector& resources = accessor.GetResources();
843 for (Resource* resource : resources) {
844 resource->Release(can_make_gl_calls);
849 AcquireOrReleaseResourceIndex(
true, resource_index_);
854 template <
typename T>
void ProcessDataRequests() {
856 std::vector<DataRequest<T> >& requests = *GetDataRequestVector<T>();
857 const size_t request_count = requests.size();
858 std::vector<T> infos(1);
859 for (
size_t i = 0; i < request_count; ++i) {
861 FillDataFromRenderer(requests[i].
id, &info);
865 requests[i].callback(infos);
871 template <
typename HolderType,
typename InfoType>
872 void ProcessInfoRequests(ResourceContainer* resource_container,
873 ResourceBinder* resource_binder) {
875 std::vector<ResourceRequest<HolderType, InfoType> >& requests =
876 *GetResourceRequestVector<HolderType, InfoType>();
877 const size_t request_count = requests.size();
878 for (
size_t i = 0; i < request_count; ++i)
879 ProcessInfoRequest<HolderType, InfoType>(requests[i], resource_container,
885 template <
typename HolderType,
typename InfoType>
886 void ProcessInfoRequest(
const ResourceRequest<HolderType, InfoType>& request,
887 ResourceContainer* resource_container,
888 ResourceBinder* resource_binder) {
889 typedef typename HolderToResource<HolderType>::ResourceType
ResourceType;
890 std::vector<InfoType> infos;
891 if (request.holder.Get()) {
896 if (ResourceType* resource =
897 GetResource(request.holder.Get(), resource_binder))
898 AppendResourceInfo(&infos, resource, resource_binder);
901 ResourceAccessor accessor(*resource_container);
902 ResourceVector& resources = accessor.GetResources();
903 const std::vector<ResourceKey> keys =
904 GetAllResourceKeys<ResourceType>(resource_binder);
905 std::unordered_set<ResourceKey> key_set(keys.begin(), keys.end());
906 for (Resource* resource : resources) {
907 if (key_set.find(resource->GetKey()) != key_set.end()) {
908 ResourceType* typed_resource =
static_cast<ResourceType*
>(resource);
909 AppendResourceInfo(&infos, typed_resource, resource_binder);
914 request.callback(infos);
919 template <
typename InfoType,
typename ResourceType>
920 void AppendResourceInfo(std::vector<InfoType>* infos,
921 ResourceType* resource, ResourceBinder* rb) {
925 info.id = resource->GetId();
926 info.label = resource->GetHolder()->GetLabel();
927 FillInfoFromResource(&info, resource, rb);
930 resource->Unbind(rb);
931 infos->push_back(info);
935 template <
typename InfoType,
typename ResourceType>
936 void FillInfoFromResource(InfoType* info, ResourceType* resource,
937 ResourceBinder* rb) {}
940 template <
typename InfoType>
941 void FillDataFromRenderer(GLuint
id, InfoType* info);
950 AtomicSizeT() :
value(0U) {}
951 AtomicSizeT(
const AtomicSizeT& other) :
value(other.
value.load()) {}
952 AtomicSizeT&
operator=(
const AtomicSizeT& other) {
953 value = other.value.load();
956 std::atomic<size_t>
value;
962 static size_t AcquireOrReleaseResourceIndex(
bool is_release,
size_t index) {
963 typedef std::set<size_t> IndexSet;
967 size_t new_index = index;
968 IndexSet::const_iterator end = used_indices->end();
970 IndexSet::iterator it = used_indices->find(index);
972 used_indices->erase(it);
979 while (used_indices->find(new_index) != end)
981 used_indices->insert(new_index);
987 template <
typename HolderType>
988 typename HolderToResource<HolderType>::ResourceType* CreateResource(
989 const HolderType* holder, ResourceBinder* binder,
ResourceKey key,
993 size_t resource_index_;
999 base::AllocVector<AtomicSizeT> memory_usage_;
1005 ResourceVector resources_to_release_;
1009 port::Mutex release_mutex_;
1022 class Renderer::ResourceBinder :
public Allocatable {
1024 typedef base::AllocVector<Uniform> UniformStack;
1027 struct BufferBinding {
1028 BufferBinding() :
buffer(0U), resource(nullptr) {}
1030 BufferResource* resource;
1035 ImageUnit() : sampler(0U), resource(nullptr) {}
1037 TextureResource* resource;
1044 class StreamAnnotator :
public base::Allocatable {
1047 void Push(
const std::string& label) {}
1051 class StreamAnnotator :
public base::Allocatable {
1055 gl_supports_markers_(
1056 gm_->IsFunctionGroupAvailable(GraphicsManager::kDebugMarker)) {}
1060 void Push(
const std::string& marker) {
1061 if (std::ostream* out = gm_->GetTracingStream())
1062 *out << std::string(
indent_.length(),
'-') <<
">" << marker <<
":\n";
1064 gm_->SetTracingPrefix(
indent_);
1065 if (gl_supports_markers_)
1066 gm_->PushGroupMarker(static_cast<GLsizei>(marker.length()),
1073 if (gl_supports_markers_)
1074 gm_->PopGroupMarker();
1076 gm_->SetTracingPrefix(
indent_);
1083 const bool gl_supports_markers_;
1087 class InfoRequestGuard {
1089 explicit InfoRequestGuard(ResourceBinder* rb)
1091 rb_->processing_info_requests_ =
true;
1093 ~InfoRequestGuard() {
1094 rb_->processing_info_requests_ =
false;
1098 ResourceBinder* rb_;
1103 : graphics_manager_(gm),
1104 stream_annotator_(new (
GetAllocator()) StreamAnnotator(gm)),
1105 image_units_(*this),
1106 texture_last_bindings_(*this),
1107 active_image_unit_(kInvalidGluint),
1108 active_framebuffer_(kInvalidGluint),
1109 active_framebuffer_resource_(nullptr),
1110 active_shader_id_(0U),
1111 active_shader_resource_(nullptr),
1112 active_vertex_array_(0U),
1113 active_vertex_array_resource_(nullptr),
1114 current_shader_program_(nullptr),
1115 vertex_array_keys_(*this),
1116 gl_state_table_(new (
GetAllocator()) StateTable(0, 0)),
1117 client_state_table_(new (
GetAllocator()) StateTable(0, 0)),
1118 traversal_state_tables_(*this),
1119 current_traversal_index_(0U),
1120 processing_info_requests_(false) {
1121 memset(saved_ids_, 0,
sizeof(saved_ids_));
1122 saved_state_table_ =
new (
GetAllocator()) StateTable();
1129 gm->Enable(GL_PROGRAM_POINT_SIZE);
1138 image_units_.resize(max_image_units);
1140 TextureManager(max_image_units));
1141 DCHECK(texture_manager_.get());
1143 traversal_state_tables_.resize(16);
1144 for (
size_t i = 0; i < 16U; ++i)
1145 traversal_state_tables_[i] =
new(
GetAllocator()) StateTable;
1148 ~ResourceBinder()
override {}
1158 return graphics_manager_;
1163 TextureManager* GetTextureManager()
const {
return texture_manager_.get(); }
1168 void SetResourceManager(ResourceManager* manager) {
1169 resource_manager_ = manager;
1173 StreamAnnotator* GetStreamAnnotator()
const {
1174 return stream_annotator_.get();
1179 return current_fbo_.Acquire();
1184 current_fbo_ = base::WeakReferentPtr<FramebufferObject>(fbo);
1188 ShaderProgramResource* GetActiveShaderProgram()
const {
1189 return active_shader_resource_;
1193 FramebufferResource* GetActiveFramebuffer()
const {
1194 return active_framebuffer_resource_;
1198 VertexArrayResource* GetActiveVertexArray()
const {
1199 return active_vertex_array_resource_;
1206 void SetActiveVertexArray(VertexArrayResource* resource) {
1207 active_vertex_array_resource_ = resource;
1212 StateTable*
GetStateTable()
const {
return gl_state_table_.Get(); }
1216 BufferResource* resource);
1223 bool BindProgram(GLuint
id, ShaderProgramResource* resource);
1227 void BindSamplerToUnit(GLuint
id, GLuint unit) {
1229 if (!
id ||
id != image_units_[unit].sampler) {
1230 image_units_[unit].sampler =
id;
1236 void ActivateUnit(GLuint unit);
1240 void BindTextureToUnit(TextureResource* resource, GLuint unit);
1243 bool WasTextureEvicted(TextureResource* resource) {
1244 auto found = texture_last_bindings_.find(resource);
1245 if (found == texture_last_bindings_.end())
1247 if (image_units_[found->second].resource == resource)
1253 int GetLastBoundUnit(TextureResource* resource) {
1254 auto found = texture_last_bindings_.find(resource);
1255 if (found != texture_last_bindings_.end())
1256 return found->second;
1260 void ClearAssignedImageUnit(TextureResource* resource) {
1261 texture_last_bindings_.erase(resource);
1265 void BindVertexArray(GLuint
id, VertexArrayResource* resource);
1269 if (!
id ||
id == active_buffers_[target].
buffer) {
1270 active_buffers_[target].buffer = 0;
1271 active_buffers_[target].resource =
nullptr;
1276 void ClearFramebufferBinding(GLuint
id) {
1277 if (!
id ||
id == active_framebuffer_) {
1278 active_framebuffer_ = kInvalidGluint;
1279 active_framebuffer_resource_ =
nullptr;
1284 void ClearProgramBinding(GLuint
id) {
1285 if (!
id ||
id == active_shader_id_) {
1286 active_shader_id_ = 0;
1287 active_shader_resource_ =
nullptr;
1292 void ClearSamplerBindings(GLuint
id) {
1293 const size_t count = image_units_.size();
1294 for (
size_t i = 0; i < count; ++i)
1295 if (
id == image_units_[i].sampler)
1296 image_units_[i].sampler = 0;
1301 void ClearTextureBinding(GLuint
id, GLuint unit);
1304 void ClearVertexArrayBinding(GLuint
id);
1307 void ClearNonFramebufferCachedBindings();
1309 template <
typename HolderType>
1312 if (
typename HolderToResource<HolderType>::ResourceType* resource =
1313 resource_manager_->GetResource(holder,
this)) {
1315 resource->Update(
this);
1324 struct CreateOrUpdateOp {
1325 template <
typename HolderType>
1326 static void Process(ResourceBinder* rb,
const HolderType* holder,
1329 typename HolderToResource<HolderType>::ResourceType* resource =
1330 rb->GetResourceManager()->GetResource(holder, rb, gl_id);
1336 resource->UnbindAll();
1339 if (resource->AnyModifiedBitsSet())
1340 resource->Update(rb);
1348 struct RequestUpdateOp {
1349 template <
typename HolderType>
1350 static void Process(ResourceBinder* rb,
const HolderType* holder,
1353 Renderer::SetResourceHolderBit(holder,
1363 template <
typename Operation,
typename HolderType>
1364 struct OperationImpl {
1365 static void Process(ResourceBinder* rb,
const HolderType* holder,
1367 Operation::Process(rb, holder, gl_id);
1372 template <
typename Operation>
1373 struct OperationImpl<Operation, AttributeArray> {
1374 static void Process(ResourceBinder* rb,
const AttributeArray* aa,
1376 if (aa ==
nullptr)
return;
1378 std::set<BufferObject*> buffers;
1379 const size_t buffer_attribute_count = aa->GetBufferAttributeCount();
1380 for (
size_t i = 0; i < buffer_attribute_count; ++i) {
1381 const Attribute& a = aa->GetBufferAttribute(i);
1382 if (BufferObject* bo =
1383 a.GetValue<BufferObjectElement>().buffer_object.Get()) {
1385 if (buffers.find(bo) == buffers.end()) {
1386 Operation::Process(rb, bo, gl_id);
1391 GraphicsManager* gm = rb->GetGraphicsManager().Get();
1393 Operation::Process(rb, aa, gl_id);
1395 Operation::Process(rb,
1396 reinterpret_cast<const AttributeArrayEmulator*>(aa), gl_id);
1403 template <
typename Operation,
typename HolderType>
1404 void Process(
const HolderType* holder, GLuint gl_id) {
1405 OperationImpl<Operation, HolderType>::Process(
this, holder, gl_id);
1412 template <
typename Operation>
1413 void Traverse(
const NodePtr& node, ShaderProgram* default_shader);
1416 template <
typename Operation>
1417 void VisitShape(
const ShapePtr& shape);
1431 void SendUniform(
const Uniform& uniform,
int location, GraphicsManager* gm);
1435 void PushUniforms(
const Node* node,
1436 const base::AllocVector<Uniform>& uniforms);
1439 void PopUniforms(
const base::AllocVector<Uniform>& uniforms);
1449 size_t GetImageUnitCount()
const {
return image_units_.size(); }
1451 void SetImageUnitRange(
const Range1i& units) {
1455 const GLuint count =
static_cast<GLuint
>(GetImageUnitCount());
1456 for (GLuint i = max_image_units; i < count; ++i) {
1457 ClearTextureBinding(0U, i);
1459 ClearSamplerBindings(0U);
1460 texture_manager_->SetUnitRange(units);
1470 ShaderProgram* default_shader);
1474 bool IsProcessingInfoRequests()
const {
return processing_info_requests_; }
1480 auto key_iterator = vertex_array_keys_.find(GetActiveShaderProgram());
1481 if (key_iterator == vertex_array_keys_.end()) {
1483 &*vertex_array_keys_.insert(GetActiveShaderProgram()).first);
1485 return reinterpret_cast<ResourceKey>(&*key_iterator);
1488 std::vector<ResourceKey> GetAllVertexArrayKeys() {
1489 std::vector<ResourceKey> keys;
1490 for (
const auto &i : vertex_array_keys_) {
1491 keys.push_back(reinterpret_cast<ResourceKey>(&i));
1498 void EraseVertexArrayKey(ShaderProgramResource *shader) {
1499 vertex_array_keys_.erase(shader);
1507 void DrawNode(
const Node& node, GraphicsManager* gm);
1509 void DrawShape(
const Shape& shape, GraphicsManager* gm);
1511 void DrawIndexedShape(
const Shape& shape,
const IndexBuffer& ib,
1512 GraphicsManager* gm);
1514 void DrawNonindexedShape(
const Shape& shape,
size_t vertex_count,
1515 GraphicsManager* gm);
1519 void MarkAttachmentImplicitlyChanged(
1520 const FramebufferObject::Attachment& attachment);
1524 template <
typename Operation>
1525 void Visit(
const NodePtr& node);
1531 std::unique_ptr<StreamAnnotator> stream_annotator_;
1536 std::unique_ptr<TextureManager> texture_manager_;
1539 base::WeakReferentPtr<FramebufferObject> current_fbo_;
1542 base::AllocVector<ImageUnit> image_units_;
1544 base::AllocUnorderedMap<TextureResource*, GLuint> texture_last_bindings_;
1545 GLuint active_image_unit_;
1548 std::array<BufferBinding, 4> active_buffers_;
1553 GLuint active_framebuffer_;
1554 FramebufferResource* active_framebuffer_resource_;
1557 GLuint active_shader_id_;
1558 ShaderProgramResource* active_shader_resource_;
1561 GLuint active_vertex_array_;
1562 VertexArrayResource* active_vertex_array_resource_;
1572 ResourceManager* resource_manager_;
1575 ShaderProgram* current_shader_program_;
1582 base::AllocSet<ShaderProgramResource*> vertex_array_keys_;
1589 base::AllocVector<StateTablePtr> traversal_state_tables_;
1590 size_t current_traversal_index_;
1593 bool processing_info_requests_;
1595 friend class InfoRequestGuard;
1601 ResourceKey Renderer::ResourceManager::GetResourceKey<
1602 Renderer::VertexArrayResource>(ResourceBinder* resource_binder,
1604 return resource_binder->GetVertexArrayKey();
1607 std::vector<ResourceKey> Renderer::ResourceManager::GetAllResourceKeys<
1608 Renderer::VertexArrayResource>(ResourceBinder* resource_binder) {
1609 return resource_binder->GetAllVertexArrayKeys();
1613 ResourceKey Renderer::ResourceManager::GetResourceKey<
1614 Renderer::VertexArrayEmulatorResource>(ResourceBinder* resource_binder,
1616 return resource_binder->GetVertexArrayKey();
1619 std::vector<ResourceKey> Renderer::ResourceManager::GetAllResourceKeys<
1620 Renderer::VertexArrayEmulatorResource>(ResourceBinder* resource_binder) {
1621 return resource_binder->GetAllVertexArrayKeys();
1625 ResourceKey Renderer::ResourceManager::GetResourceKey<
1626 Renderer::ShaderInputRegistryResource>(ResourceBinder* resource_binder,
1628 return reinterpret_cast<ResourceKey>(resource_binder);
1632 ResourceKey Renderer::ResourceManager::GetResourceKey<
1633 Renderer::FramebufferResource>(ResourceBinder* resource_binder,
1635 return reinterpret_cast<ResourceKey>(resource_binder);
1639 ResourceKey Renderer::ResourceManager::GetResourceKey<
1640 Renderer::ShaderProgramResource>(ResourceBinder* resource_binder,
1648 return reinterpret_cast<ResourceKey>(resource_binder);
1654 std::vector<ResourceKey> Renderer::ResourceManager::GetAllResourceKeys<
1655 Renderer::ShaderProgramResource>(ResourceBinder* resource_binder) {
1656 std::vector<ResourceKey> keys;
1657 keys.push_back(reinterpret_cast<ResourceKey>(resource_binder));
1658 keys.push_back(reinterpret_cast<ResourceKey>(
this));
1662 void Renderer::ResourceManager::ProcessResourceInfoRequests(
1663 ResourceBinder* resource_binder) {
1664 ResourceBinder::InfoRequestGuard guard(resource_binder);
1667 ProcessInfoRequests<AttributeArray, ArrayInfo>(&resources_[kAttributeArray],
1669 ProcessInfoRequests<BufferObject, BufferInfo>(&resources_[kBufferObject],
1671 ProcessInfoRequests<FramebufferObject, FramebufferInfo>(
1672 &resources_[kFramebufferObject], resource_binder);
1673 ProcessInfoRequests<Sampler, SamplerInfo>(&resources_[kSampler],
1675 ProcessInfoRequests<ShaderProgram, ProgramInfo>(&resources_[kShaderProgram],
1677 ProcessInfoRequests<Shader, ShaderInfo>(&resources_[kShader],
1679 ProcessInfoRequests<TextureBase, TextureInfo>(&resources_[kTexture],
1681 ProcessDataRequests<PlatformInfo>();
1682 ProcessDataRequests<TextureImageInfo>();
1688 class Renderer::ScopedLabel {
1690 ScopedLabel(ResourceBinder* binder,
const void* address,
1691 const std::string& label) {}
1694 class Renderer::ScopedLabel {
1696 ScopedLabel(ResourceBinder* rb,
const void* address,
1697 const std::string& label)
1698 : annotator_(rb->GetStreamAnnotator()),
1700 if (rb->GetGraphicsManager()->GetTracingStream() && label.length()) {
1711 ResourceBinder::StreamAnnotator* annotator_;
1730 template <
int NumModifiedBits>
1731 class Renderer::Resource :
public Renderer::ResourceManager::Resource {
1733 class ScopedResourceLabel :
public ScopedLabel {
1735 ScopedResourceLabel(Resource* resource, ResourceBinder* binder)
1736 : ScopedLabel(binder, resource->GetHolder(),
1737 resource->GetHolder()->GetLabel()) {}
1740 ~Resource()
override { DetachFromHolder(); }
1742 bool AnyModifiedBitsSet()
const {
return modified_bits_.any(); }
1744 void OnDestroyed()
override {
1752 GLuint GetId()
const {
return id_; }
1755 typedef Renderer::Resource<NumModifiedBits> BaseResourceType;
1757 Resource(ResourceManager* rm,
const ResourceHolder& holder,
ResourceKey key,
1759 :
Renderer::ResourceManager::Resource(rm, &holder, key),
1761 resource_owns_gl_id_(id == 0U) {
1774 bool HasHolder()
const {
return GetHolder() !=
nullptr; }
1776 void Release(
bool can_make_gl_calls)
override { DetachFromHolder(); }
1779 void OnChanged(
const int bit)
override { modified_bits_.set(bit); }
1781 void ResetModifiedBit(
int bit) { modified_bits_.reset(bit); }
1783 void ResetModifiedBits() { modified_bits_.reset(); }
1785 void SetModifiedBit(
int bit) { modified_bits_.set(bit); }
1787 void SetModifiedBits() { modified_bits_.set(); }
1789 bool TestModifiedBit(
int bit)
const {
return modified_bits_.test(bit); }
1793 bool TestModifiedBitRange(
int low_bit,
int high_bit)
const {
1794 std::bitset<NumModifiedBits> mask;
1799 mask <<= high_bit + 1 - low_bit;
1806 return (mask & modified_bits_).any();
1809 const std::bitset<NumModifiedBits>& GetBits()
const {
return modified_bits_; }
1811 friend class ResourceBinder;
1816 const bool resource_owns_gl_id_;
1819 void DetachFromHolder() {
1821 const ResourceHolder* holder =
GetHolder();
1826 if (holder->GetResource(index,
GetKey()) ==
this) {
1829 holder->SetResource(index,
GetKey(),
nullptr);
1834 std::bitset<NumModifiedBits> modified_bits_;
1845 class Renderer::SamplerResource :
public Resource<Sampler::kNumChanges> {
1847 SamplerResource(ResourceBinder* rb, ResourceManager* rm,
1848 const Sampler& sampler,
ResourceKey key, GLuint
id)
1849 :
Renderer::Resource<Sampler::kNumChanges>(rm, sampler, key, id) {}
1851 ~SamplerResource()
override {
1855 void Release(
bool can_make_gl_calls)
override;
1856 void Update(ResourceBinder* rb)
override;
1857 ResourceType GetType()
const override {
return kSampler; }
1861 void Bind(ResourceBinder* rb) { Update(rb); }
1862 void Unbind(ResourceBinder* rb)
override;
1865 void BindToUnit(GLuint unit, ResourceBinder* rb);
1867 const Sampler& GetSampler()
const {
1868 return static_cast<const Sampler&
>(*
GetHolder());
1872 void Renderer::SamplerResource::Update(ResourceBinder* rb) {
1873 if (GetGraphicsManager()->IsFunctionGroupAvailable(
1875 const Sampler& sampler = GetSampler();
1877 if (AnyModifiedBitsSet()) {
1878 ScopedResourceLabel
label(
this, rb);
1880 GraphicsManager* gm = GetGraphicsManager();
1882 if (!id_) gm->GenSamplers(1, &id_);
1889 gm->IsExtensionSupported(
"texture_filter_anisotropic")) {
1891 std::min(sampler.GetMaxAnisotropy(),
1892 gm->GetCapabilityValue<
float>(
1894 gm->SamplerParameterf(id_, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
1897 gm->SamplerParameteri(
1898 id_, GL_TEXTURE_MIN_FILTER,
1901 gm->SamplerParameteri(
1902 id_, GL_TEXTURE_MAG_FILTER,
1905 gm->SamplerParameteri(
1906 id_, GL_TEXTURE_WRAP_S,
1909 gm->SamplerParameteri(
1910 id_, GL_TEXTURE_WRAP_T,
1913 gm->SamplerParameteri(
1914 id_, GL_TEXTURE_COMPARE_FUNC,
1917 gm->SamplerParameteri(
1918 id_, GL_TEXTURE_COMPARE_MODE,
1920 ? GL_COMPARE_REF_TO_TEXTURE
1923 gm->SamplerParameterf(id_, GL_TEXTURE_MAX_LOD, sampler.GetMaxLod());
1925 gm->SamplerParameterf(id_, GL_TEXTURE_MIN_LOD, sampler.GetMinLod());
1927 gm->SamplerParameteri(
1928 id_, GL_TEXTURE_WRAP_R,
1931 ResetModifiedBits();
1933 LOG(
ERROR) <<
"***ION: Unable to create sampler object";
1939 void Renderer::SamplerResource::BindToUnit(GLuint unit, ResourceBinder* rb) {
1942 rb->BindSamplerToUnit(id_, unit);
1945 void Renderer::SamplerResource::Unbind(ResourceBinder* rb) {
1947 rb->ClearSamplerBindings(id_);
1950 void Renderer::SamplerResource::Release(
bool can_make_gl_calls) {
1951 BaseResourceType::Release(can_make_gl_calls);
1954 if (resource_owns_gl_id_ && can_make_gl_calls)
1955 GetGraphicsManager()->DeleteSamplers(1, &id_);
1970 class Renderer::TextureResource :
public Resource<CubeMapTexture::kNumChanges> {
1972 TextureResource(ResourceBinder* rb, ResourceManager* rm,
1974 :
Renderer::Resource<CubeMapTexture::kNumChanges>(rm, texture, key, id),
1976 last_uploaded_components_(0U),
1977 auto_mipmapping_enabled_(false),
1978 max_anisotropy_(0.f),
1988 multisample_enabled_by_renderer_(false) {
1993 ~TextureResource()
override {
1998 void Update(ResourceBinder* rb)
override;
1999 void Release(
bool can_make_gl_calls)
override;
2001 ResourceType GetType()
const override {
return kTexture; }
2003 GLenum GetGlTarget()
const {
return gl_target_; }
2005 template <
typename T>
const T& GetTexture()
const {
2006 return static_cast<const T&
>(*(this->
GetHolder()));
2011 void Bind(ResourceBinder* rb);
2013 void BindToUnit(ResourceBinder* rb, GLuint unit);
2014 void Unbind(ResourceBinder* rb)
override;
2016 void OnDestroyed()
override {
2018 Renderer::Resource<CubeMapTexture::kNumChanges>::OnDestroyed();
2022 GLuint ObtainImageUnit(ResourceBinder* rb,
const void* assoc,
int old_unit) {
2025 const int unit = rb->GetTextureManager()->GetUnit(assoc, old_unit);
2026 return static_cast<GLuint
>(unit);
2030 bool SetMultisampleEnabledByRenderer(
bool multisample_enabled_by_renderer) {
2031 const bool changed = multisample_enabled_by_renderer_ !=
2032 multisample_enabled_by_renderer;
2033 multisample_enabled_by_renderer_ = multisample_enabled_by_renderer;
2039 bool IsComplete()
const;
2042 void UpdateCubeMapImageState(GraphicsManager* gm);
2043 void UpdateTextureImageState(GraphicsManager* gm,
bool multisample,
2044 bool multisample_changed);
2047 void CreateImmutableTexture(
const Image& image,
const bool multisample,
2048 const size_t samples,
2049 const bool fixed_sample_locations,
size_t levels,
2050 GraphicsManager* gm);
2052 bool CheckImage(
const Image& image,
const TextureBase& texture);
2053 void UploadImage(
const Image& image, GLenum target, GLint
level,
2054 int samples,
bool fixed_sample_locations,
2055 bool is_full_image,
const Point3ui&
offset,
2056 GraphicsManager* gm);
2058 void UpdateMipmapGeneration(
const Sampler& sampler,
bool image_has_changed,
2059 GraphicsManager* gm);
2060 bool UpdateMipmap0Image(
const Image& image,
const TextureBase& texture,
2061 const size_t mipmap_count, GLenum target,
2062 int mipmap_changed_bit, GraphicsManager* gm,
2063 size_t* required_levels,
bool multisample_changed);
2064 bool UpdateImage(
const Image& image0,
const Image& image,
2065 const TextureBase& texture, GLenum target,
int level,
2066 GraphicsManager* gm);
2067 void UpdateState(
const TextureBase& texture, ResourceBinder* rb, GLuint unit);
2068 void UpdateSamplerState(
const Sampler& sampler, GraphicsManager* gm);
2069 void UpdateSubImages(
const base::AllocVector<Texture::SubImage>& images,
2070 GLenum target, GraphicsManager* gm);
2071 void UpdateTextureState(
const TextureBase& texture, GraphicsManager* gm);
2074 int last_uploaded_components_;
2077 bool auto_mipmapping_enabled_;
2078 float max_anisotropy_;
2090 bool multisample_enabled_by_renderer_;
2094 void UpdateWithUnit(ResourceBinder* rb, GLuint unit);
2097 void UpdateTextureTarget(GraphicsManager* gm,
const bool multisample) {
2099 const TextureBase& base = GetTexture<TextureBase>();
2100 Image* image = base.GetImmutableImage().Get();
2103 UpdateCubeMapTextureTypeFromImage(*image);
2105 const CubeMapTexture& texture = GetTexture<CubeMapTexture>();
2107 UpdateCubeMapTextureTypeFromImage(
2113 UpdateTextureTypeFromImage(*image, multisample);
2115 const Texture& texture = GetTexture<Texture>();
2116 if (texture.HasImage(0U))
2117 UpdateTextureTypeFromImage(*texture.GetImage(0U), multisample);
2124 void UpdateTextureTypeFromImage(
const Image& image,
bool multisample) {
2126 gl_target_ = GL_TEXTURE_2D;
2132 gl_target_ = GL_TEXTURE_1D_ARRAY;
2135 gl_target_ = GL_TEXTURE_2D_MULTISAMPLE;
2137 gl_target_ = GL_TEXTURE_2D;
2140 }
else if (image.GetDimensions() ==
Image::k3d) {
2143 gl_target_ = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
2145 gl_target_ = GL_TEXTURE_2D_ARRAY;
2148 gl_target_ = GL_TEXTURE_3D;
2155 void UpdateCubeMapTextureTypeFromImage(
const Image& image) {
2157 gl_target_ = GL_TEXTURE_2D;
2163 gl_target_ = GL_TEXTURE_CUBE_MAP_ARRAY;
2165 gl_target_ = GL_TEXTURE_CUBE_MAP;
2171 void Renderer::TextureResource::Bind(ResourceBinder* rb) {
2172 const GLuint unit = ObtainImageUnit(rb,
this, rb->GetLastBoundUnit(
this));
2173 BindToUnit(rb, unit);
2176 void Renderer::TextureResource::BindToUnit(ResourceBinder* rb, GLuint unit) {
2177 UpdateWithUnit(rb, unit);
2179 ScopedResourceLabel
label(
this, rb);
2180 rb->BindTextureToUnit(
this, unit);
2181 Sampler* sampler = GetTexture<TextureBase>().GetSampler().Get();
2183 GetGraphicsManager()->IsFunctionGroupAvailable(
2187 SamplerResource* sr = GetResource(sampler, rb);
2189 sr->BindToUnit(unit, rb);
2194 void Renderer::TextureResource::Update(ResourceBinder* rb) {
2195 if ((AnyModifiedBitsSet() || rb->WasTextureEvicted(
this)) && IsComplete()) {
2196 const GLuint unit = ObtainImageUnit(rb,
this,
2197 rb->GetLastBoundUnit(
this));
2198 UpdateWithUnit(rb, unit);
2202 void Renderer::TextureResource::UpdateWithUnit(ResourceBinder* rb,
2204 if ((AnyModifiedBitsSet() || rb->WasTextureEvicted(
this)) && IsComplete())
2205 UpdateState(GetTexture<TextureBase>(), rb, unit);
2208 bool Renderer::TextureResource::CheckImage(
const Image& image,
2209 const TextureBase& texture) {
2211 if (Sampler* sampler = texture.GetSampler().Get()) {
2222 <<
"***ION: Non-power-of-two textures using wrap mode "
2223 <<
"CLAMP_TO_EDGE must use either NEAREST or LINEAR minification "
2224 <<
"filter modes, use Texture::SetMinFilter(Sampler::kNearest) "
2225 <<
"or Texture::SetMinFilter(Sampler::kLinear) to fix this";
2233 void Renderer::TextureResource::UploadImage(
const Image& image, GLenum target,
2234 GLint
level,
int samples,
2235 bool fixed_sample_locations,
2238 GraphicsManager* gm) {
2239 const Image::PixelFormat pf =
2241 const int component_count =
2243 if (last_uploaded_components_ &&
2244 component_count < last_uploaded_components_) {
2246 <<
"While uploading image data for texture \""
2247 << GetTexture<TextureBase>().GetLabel()
2248 <<
"\", the number of components for this upload is " << component_count
2249 <<
" but was " << last_uploaded_components_
2250 <<
" the last time data was uploaded. This is likely not what you want "
2251 "as GL implementations are not guaranteed to provide particular "
2252 "values for the unset components.";
2254 last_uploaded_components_ = component_count;
2257 const void* data = container.Get() ? container->GetData() :
nullptr;
2258 gm->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
2260 const bool multisample = (samples > 0) &&
2269 gl_target_ == GL_TEXTURE_2D);
2270 gm->EGLImageTargetTexture2DOES(gl_target_, const_cast<void*>(data));
2272 }
else if (image.GetWidth() > 0U && image.GetHeight() > 0U &&
2273 image.GetDepth() > 0U) {
2277 if (image.IsCompressed() && data) {
2280 image.GetFormat(), image.GetWidth(), image.GetHeight());
2281 if (is_full_image) {
2282 gm->CompressedTexImage2D(target, level, pf.internal_format,
2283 image.GetWidth(), image.GetHeight(), 0,
2284 static_cast<GLsizei
>(data_size), data);
2286 gm->CompressedTexSubImage2D(target, level, offset[0], offset[1],
2287 image.GetWidth(), image.GetHeight(),
2289 static_cast<GLsizei
>(data_size), data);
2291 }
else if (image.GetDimensions() ==
Image::k3d) {
2292 const size_t data_size =
2294 image.GetHeight(), image.GetDepth());
2296 if (is_full_image) {
2297 gm->CompressedTexImage3D(target, level, pf.internal_format,
2298 image.GetWidth(), image.GetHeight(),
2299 image.GetDepth(), 0,
2300 static_cast<GLsizei
>(data_size), data);
2302 gm->CompressedTexSubImage3D(
2303 target, level, offset[0], offset[1], offset[2],
2304 image.GetWidth(), image.GetHeight(), image.GetDepth(),
2305 pf.internal_format,
static_cast<GLsizei
>(data_size), data);
2308 LOG(
ERROR) <<
"***ION: 3D texturing is not supported by the local "
2309 <<
"OpenGL implementation, but Texture \""
2310 << GetTexture<TextureBase>().GetLabel()
2311 <<
"\" contains a 3D Image.";
2316 if (is_full_image) {
2318 gm->TexImage2DMultisample(target, samples, pf.internal_format,
2319 image.GetWidth(), image.GetHeight(),
2320 fixed_sample_locations);
2322 gm->TexImage2D(target, level, pf.internal_format, image.GetWidth(),
2323 image.GetHeight(), 0, pf.format, pf.type, data);
2326 gm->TexSubImage2D(target, level, offset[0], offset[1],
2327 image.GetWidth(), image.GetHeight(), pf.format,
2330 }
else if (image.GetDimensions() ==
Image::k3d) {
2332 if (is_full_image) {
2334 gm->TexImage3DMultisample(
2335 target, samples, pf.internal_format, image.GetWidth(),
2336 image.GetHeight(), image.GetDepth(), fixed_sample_locations);
2338 gm->TexImage3D(target, level, pf.internal_format,
2339 image.GetWidth(), image.GetHeight(),
2340 image.GetDepth(), 0, pf.format, pf.type, data);
2343 gm->TexSubImage3D(target, level, offset[0], offset[1], offset[2],
2344 image.GetWidth(), image.GetHeight(),
2345 image.GetDepth(), pf.format, pf.type, data);
2348 LOG(
ERROR) <<
"***ION: 3D texturing is not supported by the local "
2349 <<
"OpenGL implementation, but Texture \""
2350 << GetTexture<TextureBase>().GetLabel()
2351 <<
"\" contains a 3D Image.";
2357 container->WipeData();
2360 void Renderer::TextureResource::UpdateMipmapGeneration(
const Sampler& sampler,
2361 bool image_has_changed,
2362 GraphicsManager* gm) {
2363 const bool is_auto_mipmapping_enabled =
2364 sampler.IsAutogenerateMipmapsEnabled();
2365 const bool auto_mipmapping_changed =
2366 auto_mipmapping_enabled_ != is_auto_mipmapping_enabled;
2367 if (auto_mipmapping_changed)
2368 auto_mipmapping_enabled_ = is_auto_mipmapping_enabled;
2369 if ((image_has_changed || auto_mipmapping_changed ||
2371 auto_mipmapping_enabled_)
2372 gm->GenerateMipmap(gl_target_);
2375 void Renderer::TextureResource::UpdateState(
const TextureBase& texture,
2376 ResourceBinder* rb, GLuint unit) {
2378 GraphicsManager* gm = GetGraphicsManager();
2383 const bool multisample = (texture.GetMultisampleSamples() > 0) &&
2385 const bool multisample_changed = SetMultisampleEnabledByRenderer(multisample);
2387 if (!id_ || AnyModifiedBitsSet()) {
2388 ScopedResourceLabel
label(
this, rb);
2390 gm->GenTextures(1, &id_);
2392 UpdateTextureTarget(gm, multisample);
2397 rb->ClearTextureBinding(id_, unit);
2399 rb->ActivateUnit(unit);
2400 rb->BindTextureToUnit(
this, unit);
2403 if (multisample_changed ||
2405 if (Image* image = texture.GetImmutableImage().Get())
2406 CreateImmutableTexture(*image, multisample,
2407 texture.GetMultisampleSamples(),
2408 texture.IsMultisampleFixedSampleLocations(),
2409 texture.GetImmutableLevels(), gm);
2412 UpdateCubeMapImageState(gm);
2414 UpdateTextureImageState(gm, multisample, multisample_changed);
2415 UpdateMemoryUsage(texture.GetTextureType());
2417 !GetGraphicsManager()->IsFunctionGroupAvailable(
2419 if (Sampler* sampler = GetTexture<TextureBase>().GetSampler().Get())
2420 UpdateSamplerState(*sampler, gm);
2421 UpdateTextureState(texture, gm);
2422 SetObjectLabel(gm, GL_TEXTURE, id_, texture.GetLabel());
2423 ResetModifiedBits();
2425 LOG(
ERROR) <<
"***ION: Unable to create texture object";
2430 void Renderer::TextureResource::UpdateSamplerState(
const Sampler& sampler,
2431 GraphicsManager* gm) {
2433 if (max_anisotropy_ != sampler.GetMaxAnisotropy() &&
2434 gm->IsExtensionSupported(
"texture_filter_anisotropic")) {
2435 max_anisotropy_ = sampler.GetMaxAnisotropy();
2436 const float aniso = std::min(
2437 max_anisotropy_, GetGraphicsManager()->GetCapabilityValue<float>(
2439 gm->TexParameterf(gl_target_, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
2441 if (min_filter_ != sampler.GetMinFilter()) {
2442 min_filter_ = sampler.GetMinFilter();
2443 gm->TexParameteri(gl_target_, GL_TEXTURE_MIN_FILTER,
2446 if (mag_filter_ != sampler.GetMagFilter()) {
2447 mag_filter_ = sampler.GetMagFilter();
2448 gm->TexParameteri(gl_target_, GL_TEXTURE_MAG_FILTER,
2451 if (wrap_s_ != sampler.GetWrapS()) {
2452 wrap_s_ = sampler.GetWrapS();
2453 gm->TexParameteri(gl_target_, GL_TEXTURE_WRAP_S,
2456 if (wrap_t_ != sampler.GetWrapT()) {
2457 wrap_t_ = sampler.GetWrapT();
2458 gm->TexParameteri(gl_target_, GL_TEXTURE_WRAP_T,
2462 if (gm->GetGlVersion() > 20) {
2464 if (compare_function_ != sampler.GetCompareFunction()) {
2465 compare_function_ = sampler.GetCompareFunction();
2466 gm->TexParameteri(gl_target_, GL_TEXTURE_COMPARE_FUNC,
2469 if (compare_mode_ != sampler.GetCompareMode()) {
2470 compare_mode_ = sampler.GetCompareMode();
2471 gm->TexParameteri(gl_target_, GL_TEXTURE_COMPARE_MODE,
2473 ? GL_COMPARE_REF_TO_TEXTURE
2476 if (max_lod_ != sampler.GetMaxLod()) {
2477 max_lod_ = sampler.GetMaxLod();
2478 gm->TexParameterf(gl_target_, GL_TEXTURE_MAX_LOD, max_lod_);
2480 if (min_lod_ != sampler.GetMinLod()) {
2481 min_lod_ = sampler.GetMinLod();
2482 gm->TexParameterf(gl_target_, GL_TEXTURE_MIN_LOD, min_lod_);
2484 if (wrap_r_ != sampler.GetWrapR()) {
2485 wrap_r_ = sampler.GetWrapR();
2486 gm->TexParameteri(gl_target_, GL_TEXTURE_WRAP_R,
2492 void Renderer::TextureResource::UpdateTextureState(
const TextureBase& texture,
2493 GraphicsManager* gm) {
2494 if (gm->GetGlVersion() > 20) {
2496 gm->TexParameteri(gl_target_, GL_TEXTURE_BASE_LEVEL,
2497 texture.GetBaseLevel());
2499 gm->TexParameteri(gl_target_, GL_TEXTURE_MAX_LEVEL,
2500 texture.GetMaxLevel());
2502 gm->GetGlVersion() >= 30) ||
2504 gm->GetGlVersion() >= 33)) {
2507 gl_target_, GL_TEXTURE_SWIZZLE_R,
2511 gl_target_, GL_TEXTURE_SWIZZLE_G,
2515 gl_target_, GL_TEXTURE_SWIZZLE_B,
2519 gl_target_, GL_TEXTURE_SWIZZLE_A,
2525 void Renderer::TextureResource::Unbind(ResourceBinder* rb) {
2529 const GLuint count =
static_cast<GLuint
>(rb->GetImageUnitCount());
2530 for (GLuint i = 0U; i < count; ++i)
2531 rb->ClearTextureBinding(id_, i);
2535 void Renderer::TextureResource::Release(
bool can_make_gl_calls) {
2536 BaseResourceType::Release(can_make_gl_calls);
2539 base::ReadLock read_lock(GetResourceBinderLock());
2541 ResourceBinderMap& binders = GetResourceBinderMap();
2542 for (ResourceBinderMap::iterator it = binders.begin();
2543 it != binders.end();
2545 Unbind(it->second.get());
2546 it->second->ClearAssignedImageUnit(
this);
2549 if (resource_owns_gl_id_ && can_make_gl_calls)
2550 GetGraphicsManager()->DeleteTextures(1, &id_);
2551 SetUsedGpuMemory(0U);
2556 bool Renderer::TextureResource::IsComplete()
const {
2558 const TextureBase& base = GetTexture<TextureBase>();
2559 if (!base.GetSampler().Get()) {
2561 << GetTexture<TextureBase>().GetLabel()
2562 <<
"\" has no Sampler! It will likely appear black.";
2567 if (base.GetImmutableImage().Get())
2571 const CubeMapTexture& texture = GetTexture<CubeMapTexture>();
2575 for (
int i = 0; i < 6; ++i) {
2578 if (!texture.HasImage(face, 0U)) {
2579 LOG(
WARNING) <<
"***ION: Cubemap texture face "
2581 <<
" has no level 0 mipmap.";
2587 const Texture& texture = GetTexture<Texture>();
2588 if (!texture.HasImage(0U)) {
2589 LOG(
WARNING) <<
"***ION: Texture \"" << texture.GetLabel()
2590 <<
"\" has no level 0 mipmap";
2598 bool Renderer::TextureResource::UpdateMipmap0Image(
2599 const Image& image,
const TextureBase& texture,
const size_t mipmap_count,
2600 GLenum target,
int mipmap_changed_bit, GraphicsManager* gm,
2601 size_t* required_levels,
bool multisample_changed) {
2602 const uint32
width = image.GetWidth();
2603 const uint32 height = image.GetHeight();
2605 const bool mipmap_changed = TestModifiedBit(mipmap_changed_bit);
2608 if ((mipmap_changed || multisample_changed) && CheckImage(image, texture)) {
2609 const int samples = texture.GetMultisampleSamples();
2610 const bool fixed_sample_locations =
2611 texture.IsMultisampleFixedSampleLocations();
2612 UploadImage(image, target, 0, samples, fixed_sample_locations,
true,
2622 return mipmap_count < *required_levels && mipmap_count > 1U;
2625 bool Renderer::TextureResource::UpdateImage(
const Image& image0,
2626 const Image& mipmap,
2627 const TextureBase& texture,
2630 GraphicsManager* gm) {
2633 uint32 expected_width = 0;
2634 uint32 expected_height = 0;
2635 if (mipmap.GetFormat() != format) {
2636 LOG(
ERROR) <<
"***ION: Mipmap level " << level <<
" has different"
2637 <<
" format [" << mipmap.GetFormat() <<
"] from level 0's ["
2638 << format <<
"], ignoring";
2645 &expected_height)) {
2647 UploadImage(mipmap, target, level, 0,
false,
true, Point3ui(), gm);
2653 void Renderer::TextureResource::UpdateSubImages(
2654 const base::AllocVector<Texture::SubImage>& images, GLenum target,
2655 GraphicsManager* gm) {
2656 const size_t count = images.size();
2657 for (
size_t i = 0; i < count; ++i) {
2658 const Image& image = *images[i].image.Get();
2660 UploadImage(image, target, static_cast<GLint>(images[i].level), 0,
false,
2661 false, images[i].offset, gm);
2665 void Renderer::TextureResource::UpdateMemoryUsage(
2667 size_t data_size = 0U;
2669 const Texture& tex = GetTexture<Texture>();
2670 if (tex.HasImage(0)) {
2671 const Image& image = *tex.GetImage(0);
2672 const Sampler* samp = tex.GetSampler().Get();
2673 const bool auto_mipmap = samp && samp->IsAutogenerateMipmapsEnabled();
2674 if (tex.GetImageCount() > 1 || auto_mipmap) {
2679 data_size = (data_size * 4) / 3;
2686 const CubeMapTexture& tex = GetTexture<CubeMapTexture>();
2689 const Sampler* samp = tex.GetSampler().Get();
2690 const bool auto_mipmap = samp && samp->IsAutogenerateMipmapsEnabled();
2695 data_size = data_size * 8;
2704 SetUsedGpuMemory(data_size);
2707 void Renderer::TextureResource::UpdateTextureImageState(
2708 GraphicsManager* gm,
const bool multisample,
2709 const bool multisample_changed) {
2710 const Texture& texture = GetTexture<Texture>();
2711 const bool mipmap_changed = TestModifiedBitRange(
2714 if ((mipmap_changed || multisample_changed) && texture.HasImage(0)) {
2716 const Image& image0 = *texture.GetImage(0);
2717 size_t required_levels = 0U;
2718 UpdateMipmap0Image(image0, texture, texture.GetImageCount(), gl_target_,
2720 multisample_changed);
2724 const Image& image0 = *texture.GetImage(0);
2725 size_t required_levels = 0U;
2726 const bool generate_mipmaps = UpdateMipmap0Image(
2727 image0, texture, texture.GetImageCount(), gl_target_,
2729 if (generate_mipmaps || multisample_changed)
2730 gm->GenerateMipmap(gl_target_);
2732 for (
size_t i = 1; i < required_levels; ++i) {
2733 if (texture.HasImage(i) &&
2734 CheckImage(*texture.GetImage(i),
texture) &&
2735 (generate_mipmaps || multisample_changed ||
2736 TestModifiedBit(static_cast<Texture::Changes>(
2737 Texture::kMipmapChanged + i)))) {
2738 UpdateImage(image0, *texture.GetImage(i),
texture, gl_target_,
2739 static_cast<int>(i), gm);
2747 UpdateSubImages(texture.GetSubImages(), gl_target_, gm);
2748 texture.ClearSubImages();
2752 if (Sampler* sampler = texture.GetSampler().Get()) {
2753 if (texture.HasImage(0U))
2754 UpdateMipmapGeneration(*sampler, multisample_changed ||
2755 TestModifiedBit(Texture::kMipmapChanged), gm);
2760 void Renderer::TextureResource::CreateImmutableTexture(
2761 const Image& image,
const bool multisample,
const size_t samples,
2762 const bool fixed_sample_locations,
size_t levels, GraphicsManager* gm) {
2763 Image::PixelFormat pf =
2767 gm->TexStorage2DMultisample(gl_target_, static_cast<GLsizei>(samples),
2768 pf.internal_format, image.GetWidth(),
2770 static_cast<GLboolean
>(
2771 fixed_sample_locations));
2774 gm->TexStorage2D(gl_target_, static_cast<GLsizei>(levels),
2775 pf.internal_format, image.GetWidth(),
2778 }
else if (image.GetDimensions() ==
Image::k3d) {
2780 gm->TexStorage3DMultisample(gl_target_, static_cast<GLsizei>(samples),
2781 pf.internal_format, image.GetWidth(),
2782 image.GetHeight(), image.GetDepth(),
2783 static_cast<GLboolean
>(
2784 fixed_sample_locations));
2786 gm->TexStorage3D(gl_target_, static_cast<GLsizei>(levels),
2787 pf.internal_format, image.GetWidth(), image.GetHeight(),
2793 void Renderer::TextureResource::UpdateCubeMapImageState(GraphicsManager* gm) {
2796 const CubeMapTexture& texture = GetTexture<CubeMapTexture>();
2797 static const int kSlotCount =
static_cast<int>(kMipmapSlotCount);
2800 bool images_have_changed =
false;
2801 bool need_to_generate_mipmaps =
false;
2802 size_t required_levels[6];
2803 for (
int i = 0; i < 6; ++i) {
2806 const int base_mipmap_bit =
2808 required_levels[i] = 0U;
2809 if (TestModifiedBitRange(base_mipmap_bit, base_mipmap_bit + kSlotCount) &&
2810 texture.HasImage(face, 0U)) {
2811 const Image& image = *texture.GetImage(face, 0U);
2813 const GLenum target = image.GetDimensions() ==
Image::k3d
2816 if (image.GetWidth() == image.GetHeight()) {
2817 if (UpdateMipmap0Image(image, texture, texture.GetImageCount(face),
2818 target, base_mipmap_bit, gm, &required_levels[i],
2820 need_to_generate_mipmaps =
true;
2821 images_have_changed =
true;
2824 LOG(
ERROR) <<
"Level 0 mimpap for face "
2826 << texture.GetLabel()
2827 <<
"\" does not have square dimensions. OpenGL requires "
2828 <<
"cubemap faces to have square dimensions";
2833 if (need_to_generate_mipmaps)
2834 gm->GenerateMipmap(gl_target_);
2837 for (
int j = 0; j < 6; ++j) {
2841 const int base_mipmap_bit =
2843 if (TestModifiedBitRange(base_mipmap_bit, base_mipmap_bit + kSlotCount) &&
2844 texture.HasImage(face, 0U)) {
2845 const Image& image0 = *texture.GetImage(face, 0U);
2846 const GLenum target = image0.GetDimensions() ==
Image::k3d
2849 for (
size_t i = 1; i < required_levels[j]; ++i) {
2850 if (texture.HasImage(face, i) &&
2851 CheckImage(*texture.GetImage(face, i),
texture) &&
2852 (need_to_generate_mipmaps ||
2853 TestModifiedBit(static_cast<int>(base_mipmap_bit + i)))) {
2854 if (!UpdateImage(image0, *texture.GetImage(face, i),
texture, target,
2855 static_cast<int>(i), gm)) {
2857 images_have_changed =
false;
2864 if (TestModifiedBit(base_subimage_bit + j)) {
2866 UpdateSubImages(texture.GetSubImages(face), target, gm);
2867 texture.ClearSubImages(face);
2872 if (Sampler* sampler = texture.GetSampler().Get())
2873 UpdateMipmapGeneration(*sampler, images_have_changed, gm);
2884 class Renderer::ShaderResource :
public Resource<Shader::kNumChanges> {
2886 ShaderResource(ResourceBinder* rb, ResourceManager* rm,
const Shader& shader,
2888 :
Renderer::Resource<Shader::kNumChanges>(rm, shader, key, id),
2889 shader_type_(GL_INVALID_ENUM) {}
2891 ~ShaderResource()
override {
2896 virtual bool UpdateShader(ResourceBinder* rb);
2897 void Release(
bool can_make_gl_calls)
override;
2898 ResourceType GetType()
const override {
return kShader; }
2901 void SetShaderType(GLenum type) { shader_type_ =
type; }
2903 const Shader& GetShader()
const {
2904 return static_cast<const Shader&
>(*
GetHolder());
2907 void Bind(ResourceBinder* rb) {}
2908 void Unbind(ResourceBinder* rb)
override {}
2909 void Update(ResourceBinder* rb)
override {}
2913 GLenum shader_type_;
2916 bool Renderer::ShaderResource::UpdateShader(ResourceBinder* rb) {
2917 if (AnyModifiedBitsSet()) {
2918 ScopedResourceLabel
label(
this, rb);
2922 const Shader& shader = GetShader();
2923 const std::string& id_string = shader.GetLabel();
2924 GraphicsManager* gm = GetGraphicsManager();
2926 std::string info_log = shader.GetInfoLog();
2929 GLuint
id = CompileShader(id_string, shader_type_, shader.GetSource(),
2934 need_to_update_label =
true;
2938 if (need_to_update_label)
2942 shader.SetInfoLog(info_log);
2943 ResetModifiedBits();
2951 void Renderer::ShaderResource::Release(
bool can_make_gl_calls) {
2952 BaseResourceType::Release(can_make_gl_calls);
2953 GraphicsManager* gm = GetGraphicsManager();
2955 if (resource_owns_gl_id_ && can_make_gl_calls)
2956 gm->DeleteShader(id_);
2972 class Renderer::ShaderInputRegistryResource
2973 :
public Resource<ShaderInputRegistry::kNumChanges> {
2975 ShaderInputRegistryResource(ResourceBinder* rb, ResourceManager* rm,
2976 const ShaderInputRegistry& reg,
2978 :
Renderer::Resource<ShaderInputRegistry::kNumChanges>(rm, reg, key, id),
2980 uniform_stacks_.reserve(reg.GetSpecs<Uniform>().size());
2983 ~ShaderInputRegistryResource()
override {}
2986 void Unbind(ResourceBinder* rb)
override {
2990 for (
auto& stack : uniform_stacks_)
2995 const Uniform& GetUniform(
size_t index)
const {
2996 DCHECK_LT(index, uniform_stacks_.size());
2997 return *uniform_stacks_[index]->GetTop();
3001 void SetInitialValue(
const Uniform& u) {
3002 DCHECK_EQ(&u.GetRegistry(), &GetRegistry());
3003 DCHECK_LT(u.GetIndexInRegistry(), uniform_stacks_.size());
3004 UniformStack& uis = *uniform_stacks_[u.GetIndexInRegistry()];
3009 void PushUniform(
const Uniform& u) {
3010 DCHECK_EQ(&u.GetRegistry(), &GetRegistry());
3011 DCHECK_LT(u.GetIndexInRegistry(), uniform_stacks_.size());
3013 UniformStack& uis = *uniform_stacks_[u.GetIndexInRegistry()];
3014 const ShaderInputRegistry::CombineFunction<Uniform>::Type& combine_func =
3016 const ShaderInputRegistry::GenerateFunction<Uniform>::Type& generate_func =
3018 const Uniform& top = *uis.GetTop();
3020 Uniform* temp = uis.GetTopTempUniform();
3021 if (combine_func && top.IsValid()) {
3023 *temp = combine_func(top, u);
3024 uis.PushTempUniform(temp);
3027 uis.PushTempUniform(temp);
3032 if (generate_func) {
3034 std::vector<Uniform> generated = generate_func(*uis.GetTop());
3035 const size_t count = generated.size();
3036 for (
size_t i = 0; i < count; ++i) {
3037 const Uniform& gen = generated[i];
3038 if (gen.IsValid()) {
3040 DCHECK_EQ(&u.GetRegistry(), &GetRegistry());
3041 DCHECK_LT(gen.GetIndexInRegistry(), uniform_stacks_.size());
3042 UniformStack& uis = *uniform_stacks_[gen.GetIndexInRegistry()];
3043 Uniform* temp = uis.GetTopTempUniform();
3045 uis.PushTempUniform(temp);
3052 void PopUniform(
const Uniform& u) {
3053 DCHECK_EQ(&u.GetRegistry(), &GetRegistry());
3054 DCHECK_LT(u.GetIndexInRegistry(), uniform_stacks_.size());
3055 uniform_stacks_[u.GetIndexInRegistry()]->Pop();
3058 void Update(ResourceBinder* rb)
override {
3059 if (AnyModifiedBitsSet()) {
3062 const size_t size = GetRegistry().GetSpecs<Uniform>().size();
3063 for (
size_t i = uniform_stacks_.size(); i < size; ++i) {
3064 uniform_stacks_.push_back(std::unique_ptr<UniformStack>(
3065 new(uniform_stacks_.get_allocator().GetAllocator()) UniformStack));
3067 ResetModifiedBits();
3080 base::AllocationManager::GetDefaultAllocatorForLifetime(
3082 temp_stack_(base::AllocationManager::GetDefaultAllocatorForLifetime(
3087 Uniform* GetTopTempUniform() {
3089 return &temp_stack_.back();
3091 const Uniform* GetTop()
const {
3092 DCHECK(!uniform_stack_.empty());
3093 return uniform_stack_.back();
3096 DCHECK(!temp_stack_.empty());
3097 DCHECK(!uniform_stack_.empty());
3098 if (IsTopATempUniform())
3099 temp_stack_.pop_back();
3100 uniform_stack_.pop_back();
3103 void PushTempUniform(Uniform* temp) {
3104 DCHECK(!uniform_stack_.empty());
3105 DCHECK(!temp_stack_.empty());
3106 DCHECK(temp == GetTopTempUniform());
3108 temp_stack_.push_back(Uniform());
3109 uniform_stack_.push_back(temp);
3112 void Push(
const Uniform* uniform) {
3113 DCHECK(!uniform_stack_.empty());
3114 DCHECK(uniform != GetTopTempUniform());
3115 uniform_stack_.push_back(uniform);
3118 void SetBottom(
const Uniform& uniform) {
3119 DCHECK(!uniform_stack_.empty());
3120 DCHECK(!temp_stack_.empty());
3121 temp_stack_[0] = uniform;
3122 uniform_stack_[0] = &temp_stack_[0];
3127 uniform_stack_.clear();
3128 temp_stack_.clear();
3133 size_t Size()
const {
return uniform_stack_.size(); }
3138 temp_stack_.push_back(Uniform());
3139 uniform_stack_.push_back(&temp_stack_.back());
3141 temp_stack_.push_back(Uniform());
3143 bool IsTopATempUniform() {
3146 const size_t size = temp_stack_.size();
3147 return (size > 1U &&
3148 uniform_stack_.back() == &temp_stack_[size - 2]);
3150 base::AllocVector<const Uniform*> uniform_stack_;
3155 base::AllocDeque<Uniform> temp_stack_;
3160 const ShaderInputRegistry& GetRegistry()
const {
3161 return static_cast<const ShaderInputRegistry&
>(*
GetHolder());
3164 base::AllocVector<std::unique_ptr<UniformStack>> uniform_stacks_;
3175 class Renderer::ShaderProgramResource
3176 :
public Resource<ShaderProgram::kNumChanges> {
3178 ShaderProgramResource(ResourceBinder* rb, ResourceManager* rm,
3179 const ShaderProgram& shader_program,
ResourceKey key,
3181 :
Renderer::Resource<ShaderProgram::kNumChanges>(rm, shader_program, key,
3185 vertex_resource_(nullptr),
3186 fragment_resource_(nullptr) {}
3188 GLint GetAttributeIndex(
3190 AttributeIndexMap::const_iterator it = attribute_index_map_.find(spec);
3191 return it == attribute_index_map_.end() ? -1 : it->second;
3194 ~ShaderProgramResource()
override {
3198 void Release(
bool can_make_gl_calls)
override;
3199 void Update(ResourceBinder* rb)
override;
3203 void Bind(ResourceBinder* rb);
3204 void Unbind(ResourceBinder* rb)
override;
3206 const ShaderProgram& GetShaderProgram()
const {
3207 return static_cast<const ShaderProgram&
>(*
GetHolder());
3211 ShaderResource* GetVertexResource()
const {
return vertex_resource_; }
3212 ShaderResource* GetFragmentResource()
const {
return fragment_resource_; }
3215 struct UniformCacheEntry {
3221 base::AllocationManager::GetDefaultAllocatorForLifetime(
3223 UniformCacheEntry(GLint location_in, GLint array_size,
3225 : location(location_in),
3229 base::AllocationManager::GetDefaultAllocatorForLifetime(
3233 const int& GetUnit(
size_t index) {
3234 DCHECK_LT(index, unit_associations.size());
3235 return unit_associations[index];
3237 void SetUnit(
size_t index,
int unit) {
3238 DCHECK_LT(index, unit_associations.size());
3239 unit_associations[index] = unit;
3246 base::AllocVector<int> unit_associations;
3250 GLint> AttributeIndexMap;
3254 void PopulateAttributeCache(GLuint
id,
const std::string& id_string,
3256 GraphicsManager* gm);
3261 void PopulateUniformCache();
3264 void UpdateUniformValues(ResourceBinder* rb);
3268 bool UpdateUnitAssociations(UniformCacheEntry* entry,
3270 const Uniform& new_uniform);
3274 bool UpdateUnitAssociationAndBind(TextureResource* txr,
3275 UniformCacheEntry* entry,
3277 size_t array_index);
3281 bool ContainsAnEvictedTexture(
const Uniform& uniform, ResourceBinder* rb);
3284 AttributeIndexMap attribute_index_map_;
3287 base::AllocVector<UniformCacheEntry> uniforms_;
3290 ShaderResource* vertex_resource_;
3291 ShaderResource* fragment_resource_;
3294 void Renderer::ShaderProgramResource::PopulateAttributeCache(
3296 GraphicsManager* gm) {
3297 GLint max_length = 0;
3298 GLint attribute_count = 0;
3300 gm->GetProgramiv(
id, GL_ACTIVE_ATTRIBUTES, &attribute_count);
3301 if (attribute_count) {
3302 attribute_index_map_.clear();
3304 gm->GetProgramiv(
id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_length);
3305 static const GLint kMaxNameLength = 4096;
3306 char name[kMaxNameLength];
3309 std::min(kMaxNameLength, max_length == 0 ? kMaxNameLength : max_length);
3319 base::AllocVector<GLenum> buffer_types(allocator);
3320 base::AllocVector<GLenum> simple_types(allocator);
3321 base::AllocVector<const ShaderInputRegistry::AttributeSpec*>
3322 buffer_attributes(allocator);
3323 base::AllocVector<const ShaderInputRegistry::AttributeSpec*>
3324 simple_attributes(allocator);
3325 for (GLint i = 0; i < attribute_count; ++i) {
3328 gm->GetActiveAttrib(
id, i, max_length, &length, &size, &type, name);
3330 reg->Find<Attribute>(name)) {
3332 buffer_attributes.push_back(spec);
3333 buffer_types.push_back(type);
3335 simple_attributes.push_back(spec);
3336 simple_types.push_back(type);
3342 if (strcmp(name,
"gl_InstanceID") != 0) {
3343 LOG(
WARNING) <<
"***ION: Attribute '" << name <<
"' used in shader '"
3344 << GetShaderProgram().GetLabel()
3345 <<
"' does not have a registry entry";
3351 GLuint attribute_index = 0;
3352 GLuint count =
static_cast<GLuint
>(buffer_attributes.size());
3353 for (GLuint i = 0; i < count; ++i) {
3354 attribute_index_map_[buffer_attributes[i]] =
3355 static_cast<GLint
>(attribute_index);
3356 gm->BindAttribLocation(
id, attribute_index,
3357 buffer_attributes[i]->name.c_str());
3358 attribute_index += GetAttributeSlotCountByGlType(buffer_types[i]);
3360 count =
static_cast<GLuint
>(simple_attributes.size());
3361 for (GLuint i = 0; i < count; ++i) {
3362 attribute_index_map_[simple_attributes[i]] =
3363 static_cast<GLint
>(attribute_index);
3364 gm->BindAttribLocation(
id, attribute_index,
3365 simple_attributes[i]->name.c_str());
3366 attribute_index += GetAttributeSlotCountByGlType(simple_types[i]);
3371 void Renderer::ShaderProgramResource::PopulateUniformCache() {
3372 const ShaderProgram& shader_program = GetShaderProgram();
3374 GraphicsManager* gm = GetGraphicsManager();
3376 GLint max_length = 0;
3377 GLuint uniform_count = 0;
3379 gm->GetProgramiv(id_, GL_ACTIVE_UNIFORMS,
3380 reinterpret_cast<GLint*>(&uniform_count));
3382 if (uniform_count) {
3383 gm->GetProgramiv(id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_length);
3384 static const GLint kMaxNameLength = 4096;
3385 char name[kMaxNameLength];
3388 std::min(kMaxNameLength, max_length == 0 ? kMaxNameLength : max_length);
3391 uniforms_.reserve(uniform_count);
3392 for (GLuint i = 0; i < uniform_count; ++i) {
3396 gm->GetActiveUniform(id_, i, max_length, &length, &size, &type, name);
3399 for (
int i = 0; i < kMaxNameLength; i++) {
3400 if (name[i] ==
'[' || name[i] == 0) {
3408 reg->Find<Uniform>(name)) {
3410 if (!ValidateUniformType(name, spec->value_type, type)) {
3411 TracingHelper helper;
3412 LOG(
WARNING) <<
"***ION: Uniform '" << name <<
"' has a"
3413 <<
" different type from its spec: spec type: "
3415 <<
", uniform type: " << helper.ToString(
"GLenum", type);
3418 const int location = gm->GetUniformLocation(id_, name);
3421 uniforms_.push_back(UniformCacheEntry(location, size, spec));
3424 LOG(
WARNING) <<
"***ION: Uniform '" << name <<
"' used in shader '"
3425 << shader_program.GetLabel()
3426 <<
"' does not have a registry entry";
3432 bool Renderer::ShaderProgramResource::ContainsAnEvictedTexture(
3433 const Uniform& uniform, ResourceBinder* rb) {
3435 if (uniform.IsValid()) {
3437 if (
const size_t count = uniform.GetCount()) {
3438 for (
size_t i = 0; i < count; ++i) {
3439 if (TextureResource* txr = GetResource(
3441 if (rb->WasTextureEvicted(txr)) {
3447 }
else if (TextureResource* txr = GetResource(
3449 ret = rb->WasTextureEvicted(txr);
3452 if (
const size_t count = uniform.GetCount()) {
3453 for (
size_t i = 0; i < count; ++i) {
3454 if (TextureResource* txr =
3455 GetResource(uniform.GetValueAt<
TexturePtr>(i).Get(), rb)) {
3456 if (rb->WasTextureEvicted(txr)) {
3462 }
else if (TextureResource* txr =
3463 GetResource(uniform.GetValue<
TexturePtr>().Get(), rb)) {
3464 ret = rb->WasTextureEvicted(txr);
3471 bool Renderer::ShaderProgramResource::UpdateUnitAssociations(
3472 UniformCacheEntry* entry, ResourceBinder* rb,
const Uniform& u) {
3473 bool changed =
false;
3475 if (
const size_t count = u.GetCount()) {
3476 for (
size_t i = 0; i < count; ++i) {
3477 if (TextureResource* txr =
3479 changed = UpdateUnitAssociationAndBind(txr, entry, rb, i) || changed;
3482 }
else if (TextureResource* txr =
3484 changed = UpdateUnitAssociationAndBind(txr, entry, rb, 0);
3487 if (
const size_t count = u.GetCount()) {
3488 for (
size_t i = 0; i < count; ++i) {
3489 if (TextureResource* txr =
3490 GetResource(u.GetValueAt<
TexturePtr>(i).Get(), rb)) {
3491 changed = UpdateUnitAssociationAndBind(txr, entry, rb, i) || changed;
3494 }
else if (TextureResource* txr =
3495 GetResource(u.GetValue<
TexturePtr>().Get(), rb)) {
3496 changed = UpdateUnitAssociationAndBind(txr, entry, rb, 0);
3502 bool Renderer::ShaderProgramResource::UpdateUnitAssociationAndBind(
3503 TextureResource* txr, UniformCacheEntry* entry, ResourceBinder* rb,
3504 size_t array_index) {
3509 const int& cached_unit = entry->GetUnit(array_index);
3511 const int last_unit_sent = cached_unit;
3512 const int new_unit =
3513 static_cast<int>(txr->ObtainImageUnit(rb, &cached_unit, cached_unit));
3515 txr->BindToUnit(rb, new_unit);
3516 entry->SetUnit(array_index, new_unit);
3520 return cached_unit != last_unit_sent;
3523 void Renderer::ShaderProgramResource::UpdateUniformValues(ResourceBinder* rb) {
3524 GraphicsManager* gm = GetGraphicsManager();
3526 const size_t uniform_count = uniforms_.size();
3527 for (
size_t i = 0; i < uniform_count; ++i) {
3528 UniformCacheEntry& entry = uniforms_[i];
3529 ShaderInputRegistryResource* sirr = GetResource(entry.spec->registry, rb);
3534 const Uniform& uniform = sirr->GetUniform(entry.spec->index);
3535 if (!uniform.IsValid()) {
3536 if (!rb->IsProcessingInfoRequests()) {
3537 LOG(
WARNING) <<
"***ION: There is no value set for uniform '"
3538 << entry.spec->name <<
"' for shader program '"
3539 << GetShaderProgram().GetLabel() <<
"', rendering"
3540 <<
" results may be unexpected";
3550 bool skip_sending_uniform =
false;
3551 bool unit_changed =
false;
3555 unit_changed = UpdateUnitAssociations(&entry, rb, uniform);
3556 skip_sending_uniform = !unit_changed;
3563 entry.uniform_stamp != uniform.GetStamp() ||
3564 ContainsAnEvictedTexture(uniform, rb)) {
3566 entry.uniform_stamp = uniform.GetStamp();
3568 ScopedLabel
label(rb, &uniform, entry.spec->name);
3569 if (!skip_sending_uniform) {
3571 rb->SendUniform(uniform, entry.location, gm);
3577 void Renderer::ShaderProgramResource::Update(ResourceBinder* rb) {
3580 vertex_resource_ =
nullptr;
3582 fragment_resource_ =
nullptr;
3584 const bool vertex_updated =
3585 vertex_resource_ && vertex_resource_->UpdateShader(rb);
3586 const bool fragment_updated =
3587 fragment_resource_ && fragment_resource_->UpdateShader(rb);
3588 if (vertex_updated || fragment_updated || AnyModifiedBitsSet()) {
3589 ScopedResourceLabel
label(
this, rb);
3590 const ShaderProgram& shader_program = GetShaderProgram();
3592 if (!vertex_resource_) {
3593 if (Shader* shader = shader_program.GetVertexShader().Get()) {
3594 if ((vertex_resource_ = GetResource(shader, rb), rb)) {
3595 vertex_resource_->SetShaderType(GL_VERTEX_SHADER);
3596 vertex_resource_->UpdateShader(rb);
3600 if (!fragment_resource_) {
3601 if (Shader* shader = shader_program.GetFragmentShader().Get()) {
3602 if ((fragment_resource_ = GetResource(shader, rb))) {
3603 fragment_resource_->SetShaderType(GL_FRAGMENT_SHADER);
3604 fragment_resource_->UpdateShader(rb);
3609 const GLuint vertex_shader_id =
3610 vertex_resource_ ? vertex_resource_->GetId() : 0;
3611 const GLuint fragment_shader_id =
3612 fragment_resource_ ? fragment_resource_->GetId() : 0;
3615 const std::string& id_string = shader_program.GetLabel();
3616 GraphicsManager* gm = GetGraphicsManager();
3618 std::string info_log = shader_program.GetInfoLog();
3619 GLuint
id = LinkShaderProgram(id_string, vertex_shader_id,
3620 fragment_shader_id, &info_log, gm);
3627 if (!reg->CheckInputsAreUnique()) {
3628 LOG(
WARNING) <<
"***ION: Registry '" << reg->GetId() <<
" contains"
3629 <<
" multiple definitions of some inputs, rendering"
3630 <<
" results may be unexpected";
3634 PopulateAttributeCache(
id, id_string, reg, gm);
3637 id = RelinkShaderProgram(id_string,
id, vertex_shader_id,
3638 fragment_shader_id, &info_log, gm);
3639 bool need_to_update_label =
3640 vertex_updated || fragment_updated ||
3644 need_to_update_label =
true;
3649 PopulateUniformCache();
3653 if (need_to_update_label)
3658 shader_program.SetInfoLog(info_log);
3659 ResetModifiedBits();
3663 void Renderer::ShaderProgramResource::Bind(ResourceBinder* rb) {
3666 ScopedResourceLabel
label(
this, rb);
3667 rb->BindProgram(id_,
this);
3669 UpdateUniformValues(rb);
3673 void Renderer::ShaderProgramResource::Unbind(ResourceBinder* rb) {
3675 rb->ClearProgramBinding(id_);
3678 void Renderer::ShaderProgramResource::Release(
bool can_make_gl_calls) {
3679 BaseResourceType::Release(can_make_gl_calls);
3682 base::ReadLock read_lock(GetResourceBinderLock());
3684 ResourceBinderMap& binders = GetResourceBinderMap();
3685 for (ResourceBinderMap::iterator it = binders.begin();
3686 it != binders.end();
3688 Unbind(it->second.get());
3689 it->second->EraseVertexArrayKey(
this);
3692 if (resource_owns_gl_id_ && can_make_gl_calls)
3693 GetGraphicsManager()->DeleteProgram(id_);
3706 class Renderer::BufferResource :
public Resource<BufferObject::kNumChanges> {
3708 BufferResource(ResourceBinder* rb, ResourceManager* rm,
3709 const BufferObject& buffer_object,
ResourceKey key, GLuint
id)
3710 :
Renderer::Resource<BufferObject::kNumChanges>(rm, buffer_object, key,
3712 target_(buffer_object.GetTarget()),
3713 gl_target_(base::EnumHelper::GetConstant(target_)) {}
3715 ~BufferResource()
override {
3719 void Release(
bool can_make_gl_calls)
override;
3720 void Update(ResourceBinder* rb)
override;
3721 ResourceType GetType()
const override {
return kBufferObject; }
3724 void Bind(ResourceBinder* rb);
3725 void Unbind(ResourceBinder* rb)
override;
3727 GLuint GetGlTarget()
const {
return gl_target_; }
3730 void UploadSubData(
const Range1ui& range,
const void* data)
const;
3731 void CopySubData(ResourceBinder* rb,
3732 BufferResource* src_resource,
3734 uint32 read_offset);
3736 void OnDestroyed()
override {
3740 Renderer::Resource<BufferObject::kNumChanges>::OnDestroyed();
3744 const BufferObject& GetBufferObject()
const {
3745 return static_cast<const BufferObject&
>(*
GetHolder());
3752 void Renderer::BufferResource::Bind(ResourceBinder* rb) {
3755 ScopedResourceLabel
label(
this, rb);
3756 rb->BindBuffer(target_, id_,
this);
3760 void Renderer::BufferResource::UploadData() {
3761 const BufferObject& bo = GetBufferObject();
3762 const size_t size = bo.GetStructSize() * bo.GetCount();
3763 SetUsedGpuMemory(size);
3764 GetGraphicsManager()->BufferData(
3765 gl_target_, size, bo.GetData().Get() ? bo.GetData()->GetData() :
nullptr,
3769 void Renderer::BufferResource::UploadSubData(
const Range1ui& range,
3770 const void* data)
const {
3771 GetGraphicsManager()->BufferSubData(
3772 gl_target_, range.GetMinPoint(), range.GetSize(), data);
3775 void Renderer::BufferResource::CopySubData(ResourceBinder* rb,
3776 BufferResource* src_resource,
3778 uint32 read_offset) {
3779 if (!src_resource || src_resource ==
this) {
3781 GetGraphicsManager()->CopyBufferSubData(
3782 gl_target_, gl_target_, read_offset, range.GetMinPoint(),
3787 GLuint src_id = src_resource->GetId();
3790 GetGraphicsManager()->CopyBufferSubData(
3791 GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER,
3792 read_offset, range.GetMinPoint(), range.GetSize());
3796 void Renderer::BufferResource::Update(ResourceBinder* rb) {
3797 if (!AnyModifiedBitsSet()) {
3800 ScopedResourceLabel
label(
this, rb);
3803 GraphicsManager* gm = GetGraphicsManager();
3806 gm->GenBuffers(1, &id_);
3808 LOG(
ERROR) <<
"***ION: Unable to create buffer object";
3814 rb->ClearBufferBinding(target_, id_);
3817 const BufferObject& bo = GetBufferObject();
3818 if (!bo.GetStructSize()) {
3819 LOG(
WARNING) <<
"***ION: Unable to update buffer object \""
3820 << bo.GetLabel() <<
"\": BufferObject's"
3821 <<
" struct size is 0";
3824 if (!bo.GetCount()) {
3825 LOG(
WARNING) <<
"***ION: Unable to update buffer object \""
3826 << bo.GetLabel() <<
"\": BufferObject's"
3827 <<
" struct count is 0";
3831 rb->BindBuffer(target_, id_,
this);
3838 ResetModifiedBits();
3844 if (bo.GetData().Get())
3845 bo.GetData()->WipeData();
3850 if (subdata_changed) {
3851 const base::AllocVector<BufferObject::BufferSubData>& sub_data =
3853 const size_t count = sub_data.size();
3854 for (
size_t i = 0; i < count; ++i) {
3855 const BufferObject::BufferSubData& sdata = sub_data[i];
3856 if (sdata.data.Get() && sdata.data->GetData()) {
3858 sdata.range, sdata.data->GetData<uint8>() + sdata.read_offset);
3861 sdata.data->WipeData();
3866 BufferResource* src_resource =
nullptr;
3867 if (sdata.src.Get()) {
3868 src_resource = GetResource(sdata.src.Get(), rb);
3871 src_resource->Update(rb);
3874 CopySubData(rb, src_resource, sdata.range, sdata.read_offset);
3880 read_range.SetWithSize(sdata.read_offset, sdata.range.GetSize());
3881 const Range1ui& write_range = sdata.range;
3886 union_range = read_range;
3887 union_range.ExtendByRange(write_range);
3888 rb->MapBufferObjectDataRange(src, kReadWrite, union_range);
3890 rb->MapBufferObjectDataRange(src, kReadOnly, read_range);
3892 switch (src->GetMappedData().data_source) {
3893 case BufferObject::MappedBufferData::kGpuMapped:
3894 case BufferObject::MappedBufferData::kDataContainer:
3896 uint8* data =
static_cast<uint8*
>(src->GetMappedPointer());
3898 write_range.GetMinPoint() - union_range.GetMinPoint(),
3900 read_range.GetMinPoint() - union_range.GetMinPoint(),
3901 write_range.GetSize());
3903 rb->MapBufferObjectDataRange(dst, kWriteOnly, write_range);
3904 memcpy(dst->GetMappedPointer(), src->GetMappedPointer(),
3905 write_range.GetSize());
3907 rb->UnmapBufferObjectData(dst);
3910 case BufferObject::MappedBufferData::kAllocated:
3911 LOG(
WARNING) <<
"***ION: Unable to copy buffer object \""
3912 << src->GetLabel() <<
"\": BufferObject's"
3913 <<
" DataContainer has been wiped and "
3914 <<
" glCopyBufferSubData is not supported.";
3918 "Invalid source for mapped BufferObject data";
3921 rb->UnmapBufferObjectData(src);
3927 void Renderer::BufferResource::Unbind(ResourceBinder* rb) {
3933 rb->ClearBufferBinding(target_, id_);
3936 void Renderer::BufferResource::Release(
bool can_make_gl_calls) {
3937 BaseResourceType::Release(can_make_gl_calls);
3940 if (resource_owns_gl_id_ && can_make_gl_calls)
3941 GetGraphicsManager()->DeleteBuffers(1, &id_);
3942 SetUsedGpuMemory(0U);
3955 class Renderer::FramebufferResource
3956 :
public Resource<FramebufferObject::kNumChanges> {
3958 FramebufferResource(ResourceBinder* rb, ResourceManager* rm,
3959 const FramebufferObject& fbo,
ResourceKey key, GLuint
id)
3960 :
Renderer::Resource<FramebufferObject::kNumChanges>(rm, fbo, key, id),
3965 ~FramebufferResource()
override {
3966 DCHECK((id_ == 0U && color0_id_ == 0U &&
3967 depth_id_ == 0U && stencil_id_ == 0U) ||
3971 void Release(
bool can_make_gl_calls)
override;
3972 void Update(ResourceBinder* rb)
override;
3976 virtual void Bind(ResourceBinder* rb);
3977 void Unbind(ResourceBinder* rb)
override;
3978 void OnDestroyed()
override {
3979 Resource<FramebufferObject::kNumChanges>::OnDestroyed();
3983 GLuint GetColor0Id()
const {
return color0_id_; }
3984 GLuint GetDepthId()
const {
return depth_id_; }
3985 GLuint GetStencilId()
const {
return stencil_id_; }
3988 const FramebufferObject& GetFramebufferObject()
const {
3989 return static_cast<const FramebufferObject&
>(*
GetHolder());
3992 void UpdateAttachment(GraphicsManager* gm, ResourceBinder* rb, GLuint*
id,
3993 GLenum target,
const FramebufferObject& fbo,
3994 const FramebufferObject::Attachment& attachment);
3996 void UpdateMemoryUsage(
const FramebufferObject& fbo);
4004 void Renderer::FramebufferResource::Bind(ResourceBinder* rb) {
4006 ScopedResourceLabel
label(
this, rb);
4007 rb->BindFramebuffer(id_,
this);
4010 void Renderer::FramebufferResource::UpdateAttachment(
4011 GraphicsManager* gm, ResourceBinder* rb, GLuint*
id, GLenum target,
4012 const FramebufferObject& fbo,
4013 const FramebufferObject::Attachment& attachment) {
4017 gm->FramebufferRenderbuffer(GL_FRAMEBUFFER, target, GL_RENDERBUFFER, 0);
4021 gm->GenRenderbuffers(1,
id);
4024 gm->BindRenderbuffer(GL_RENDERBUFFER, *
id);
4025 if (attachment.GetSamples() > 0) {
4026 gm->RenderbufferStorageMultisample(
4028 static_cast<GLsizei>(attachment.GetSamples()),
4030 fbo.GetWidth(), fbo.GetHeight());
4032 ImagePtr image = attachment.GetImage();
4033 if (image.Get() && (image->GetType() ==
Image::kEgl ||
4036 const void* data = container.Get() ? container->GetData() :
nullptr;
4039 gm->EGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
4040 const_cast<void*>(data));
4043 gm->RenderbufferStorage(
4046 fbo.GetWidth(), fbo.GetHeight());
4050 LOG(
ERROR) <<
"***ION: Unable to create renderbuffer object.";
4053 gm->FramebufferRenderbuffer(GL_FRAMEBUFFER, target, GL_RENDERBUFFER, *
id);
4056 DCHECK(attachment.GetCubeMapTexture().Get());
4059 CubeMapTexture* tex = attachment.GetCubeMapTexture().Get();
4060 TextureResource* tr = GetResource(tex, rb);
4066 const size_t mip_level = attachment.GetMipLevel();
4067 ImagePtr image = tex->GetImage(face, mip_level);
4069 format = image->GetFormat();
4071 (image->GetWidth() != fbo.GetWidth() ||
4072 image->GetHeight() != fbo.GetHeight())) {
4073 LOG(
ERROR) <<
"***ION: Mismatched CubeMapTexture and FBO dimensions: "
4074 << image->GetWidth() <<
" x " << image->GetHeight()
4076 << fbo.GetWidth() <<
" x " << fbo.GetHeight();
4084 image->Set(format, fbo.GetWidth(), fbo.GetHeight(),
4086 tex->SetImage(face, mip_level, image);
4090 gm->FramebufferTexture2D(GL_FRAMEBUFFER, target,
4092 static_cast<GLint
>(mip_level));
4095 DCHECK(attachment.GetTexture().Get());
4098 Texture* tex = attachment.GetTexture().Get();
4099 TextureResource* tr = GetResource(tex, rb);
4104 const size_t mip_level = attachment.GetMipLevel();
4105 ImagePtr image = tex->GetImage(mip_level);
4107 format = image->GetFormat();
4109 (image->GetWidth() != fbo.GetWidth() ||
4110 image->GetHeight() != fbo.GetHeight())) {
4111 LOG(
ERROR) <<
"***ION: Mismatched Texture and FBO dimensions: "
4112 << image->GetWidth() <<
" x " << image->GetHeight()
4114 << fbo.GetWidth() <<
" x " << fbo.GetHeight();
4122 image->Set(format, fbo.GetWidth(), fbo.GetHeight(),
4124 tex->SetImage(mip_level, image);
4128 gm->FramebufferTexture2D(GL_FRAMEBUFFER, target, tr->GetGlTarget(),
4129 tr->GetId(),
static_cast<GLint
>(mip_level));
4133 void Renderer::FramebufferResource::UpdateMemoryUsage(
4134 const FramebufferObject& fbo) {
4135 size_t data_size = 0U;
4138 fbo.GetWidth(), fbo.GetHeight());
4141 fbo.GetWidth(), fbo.GetHeight());
4144 fbo.GetWidth(), fbo.GetHeight());
4145 SetUsedGpuMemory(data_size);
4148 void Renderer::FramebufferResource::Update(ResourceBinder* rb) {
4149 if (AnyModifiedBitsSet()) {
4150 ScopedResourceLabel
label(
this, rb);
4153 GraphicsManager* gm = GetGraphicsManager();
4155 if (!id_) gm->GenFramebuffers(1, &id_);
4157 const FramebufferObject& fbo = GetFramebufferObject();
4160 rb->BindFramebuffer(id_,
this);
4164 UpdateAttachment(gm, rb, &color0_id_, GL_COLOR_ATTACHMENT0, fbo,
4165 fbo.GetColorAttachment(0U));
4168 UpdateAttachment(gm, rb, &depth_id_, GL_DEPTH_ATTACHMENT, fbo,
4169 fbo.GetDepthAttachment());
4172 UpdateAttachment(gm, rb, &stencil_id_, GL_STENCIL_ATTACHMENT, fbo,
4173 fbo.GetStencilAttachment());
4174 UpdateMemoryUsage(fbo);
4177 SetObjectLabel(gm, GL_FRAMEBUFFER, id_, fbo.GetLabel());
4180 const GLenum status = gm->CheckFramebufferStatus(GL_FRAMEBUFFER);
4181 if (status != GL_FRAMEBUFFER_COMPLETE) {
4183 <<
"***ION: Framebuffer is not complete (error code: 0x"
4184 << std::hex << status
4185 <<
")! One of the attachments might have a zero width or "
4186 "height or a non-drawable format for that attachment type. It "
4187 "is also possible that a texture attachment violates some "
4188 "GL-implementation specific set of constraints. Check the FBO "
4189 "dimensions and try changing the texture state of texture "
4190 "attachments (e.g. try kNearest or kLinear filtering, don't use "
4191 "kRepeat wrapping, etc.).";
4193 ResetModifiedBits();
4195 LOG(
ERROR) <<
"***ION: Unable to create framebuffer object.";
4200 void Renderer::FramebufferResource::Unbind(ResourceBinder* rb) {
4202 rb->ClearFramebufferBinding(id_);
4205 void Renderer::FramebufferResource::Release(
bool can_make_gl_calls) {
4206 BaseResourceType::Release(can_make_gl_calls);
4210 if (can_make_gl_calls) {
4212 GetGraphicsManager()->DeleteRenderbuffers(1, &color0_id_);
4214 GetGraphicsManager()->DeleteRenderbuffers(1, &depth_id_);
4216 GetGraphicsManager()->DeleteRenderbuffers(1, &stencil_id_);
4218 if (resource_owns_gl_id_)
4219 GetGraphicsManager()->DeleteFramebuffers(1, &id_);
4221 SetUsedGpuMemory(0U);
4222 color0_id_ = depth_id_ = stencil_id_ = id_ = 0;
4234 class Renderer::VertexArrayResource
4235 :
public Resource<AttributeArray::kNumChanges> {
4237 VertexArrayResource(ResourceBinder* rb, ResourceManager* rm,
4238 const AttributeArray& attribute_array,
ResourceKey key,
4240 :
Renderer::Resource<AttributeArray::kNumChanges>(rm, attribute_array,
4242 buffer_attribute_infos_(attribute_array.
GetAllocator()),
4243 simple_attribute_indices_(attribute_array.
GetAllocator()),
4245 PopulateAttributeIndices(rb);
4248 ~VertexArrayResource()
override {
4252 void Release(
bool can_make_gl_calls)
override;
4262 virtual bool BindAndCheckBuffers(
bool force_bind, ResourceBinder* rb);
4263 void Unbind(ResourceBinder* rb)
override;
4265 size_t GetVertexCount()
const {
return vertex_count_; }
4266 const ResourceBinder::BufferBinding& GetElementArrayBinding()
const {
4267 return element_array_binding_;
4269 void SetElementArrayBinding(GLuint
id, BufferResource* resource) {
4270 element_array_binding_.buffer =
id;
4271 element_array_binding_.resource = resource;
4275 const AttributeArray& GetAttributeArray()
const {
4276 return static_cast<const AttributeArray&
>(*
GetHolder());
4279 virtual bool UpdateAndCheckBuffers(ResourceBinder* rb);
4282 void BindSimpleAttributes();
4289 bool BindBufferObjectElementAttribute(GLuint attribute_index,
4290 const Attribute& a, GLuint* slots,
4291 ResourceBinder* rb);
4294 void ResetVertexCount() {
4295 vertex_count_ = std::numeric_limits<std::size_t>::max();
4298 void UpdateVertexCount(
const Attribute& a) {
4299 const BufferObjectPtr& bo = a.GetValue<BufferObjectElement>().buffer_object;
4301 if (!a.GetDivisor() ||
4307 vertex_count_ = std::min(vertex_count_, bo->GetCount());
4313 struct BufferAttributeInfo {
4314 BufferAttributeInfo() : index(kInvalidGluint), slots(0U), enabled(false) {}
4320 base::AllocVector<BufferAttributeInfo> buffer_attribute_infos_;
4321 base::AllocVector<GLuint> simple_attribute_indices_;
4326 virtual void Bind(ResourceBinder* rb) {
4328 BindAndCheckBuffers(
true, rb);
4330 void Update(ResourceBinder* rb)
override {}
4333 void PopulateAttributeIndices(ResourceBinder* rb);
4335 size_t vertex_count_;
4336 ResourceBinder::BufferBinding element_array_binding_;
4339 friend class ResourceBinder;
4340 friend class ResourceManager;
4343 void Renderer::VertexArrayResource::BindSimpleAttributes() {
4344 GraphicsManager* gm = GetGraphicsManager();
4345 const AttributeArray& aa = GetAttributeArray();
4346 const size_t attribute_count = aa.GetSimpleAttributeCount();
4347 DCHECK_EQ(attribute_count, simple_attribute_indices_.size());
4348 for (
size_t i = 0; i < attribute_count; ++i) {
4349 const Attribute& a = aa.GetSimpleAttribute(i);
4351 const GLuint& attribute_index = simple_attribute_indices_[i];
4353 switch (a.GetType()) {
4355 gm->VertexAttrib1fv(attribute_index, &a.GetValue<
float>());
4358 gm->VertexAttrib2fv(attribute_index,
4359 a.GetValue<math::VectorBase2f>().Data());
4362 gm->VertexAttrib3fv(attribute_index,
4363 a.GetValue<math::VectorBase3f>().Data());
4366 gm->VertexAttrib4fv(attribute_index,
4367 a.GetValue<math::VectorBase4f>().Data());
4373 gm->VertexAttrib2fv(attribute_index, mat.Data());
4374 gm->VertexAttrib2fv(attribute_index + 1, &mat.Data()[2]);
4380 gm->VertexAttrib3fv(attribute_index, mat.Data());
4381 gm->VertexAttrib3fv(attribute_index + 1, &mat.Data()[3]);
4382 gm->VertexAttrib3fv(attribute_index + 2, &mat.Data()[6]);
4388 gm->VertexAttrib4fv(attribute_index, mat.Data());
4389 gm->VertexAttrib4fv(attribute_index + 1, &mat.Data()[4]);
4390 gm->VertexAttrib4fv(attribute_index + 2, &mat.Data()[8]);
4391 gm->VertexAttrib4fv(attribute_index + 3, &mat.Data()[12]);
4401 bool Renderer::VertexArrayResource::BindBufferObjectElementAttribute(
4402 GLuint attribute_index,
const Attribute& a, GLuint* slots,
4403 ResourceBinder* rb) {
4405 GraphicsManager* gm = GetGraphicsManager();
4409 const BufferObjectPtr& bo = a.GetValue<BufferObjectElement>().buffer_object;
4412 LOG(
WARNING) <<
"***ION: Unable to draw shape: "
4413 <<
"BufferObject or BufferObject DataContainer is nullptr";
4417 BufferResource* vbo = GetResource(bo.Get(), rb);
4422 const size_t spec_index = a.GetValue<BufferObjectElement>().spec_index;
4425 const BufferObject::Spec& spec = bo->GetSpec(spec_index);
4432 GetAttributeSlotCountAndStride(spec.type, &stride, slots);
4433 for (GLuint i = 0; i < *slots; ++i) {
4434 gm->VertexAttribPointer(
4435 attribute_index + i, static_cast<GLuint>(spec.component_count), type,
4436 a.IsFixedPointNormalized() ? GL_TRUE : GL_FALSE,
4437 static_cast<GLuint
>(bo->GetStructSize()),
4438 reinterpret_cast<const void*>(spec.byte_offset + i * stride));
4440 gm->VertexAttribDivisor(attribute_index + i, a.GetDivisor());
4446 void Renderer::VertexArrayResource::PopulateAttributeIndices(
4447 ResourceBinder* rb) {
4451 const AttributeArray& aa = GetAttributeArray();
4452 const size_t buffer_attribute_count = aa.GetBufferAttributeCount();
4453 const size_t simple_attribute_count = aa.GetSimpleAttributeCount();
4454 buffer_attribute_infos_.resize(buffer_attribute_count);
4455 simple_attribute_indices_.resize(simple_attribute_count, kInvalidGluint);
4457 if (ShaderProgramResource* spr = rb->GetActiveShaderProgram()) {
4459 for (
size_t i = 0; i < buffer_attribute_count; ++i) {
4460 const Attribute& a = aa.GetBufferAttribute(i);
4464 const GLint index = spr->GetAttributeIndex(spec);
4466 buffer_attribute_infos_[i].index =
static_cast<GLuint
>(index);
4467 }
else if (aa.IsBufferAttributeEnabled(i)) {
4469 <<
"***ION: Attribute array contains buffer attribute '"
4470 << spec->name <<
"' but the current shader program '"
4471 << spr->GetShaderProgram().GetLabel() <<
"' does not"
4472 <<
" declare or use it";
4476 for (
size_t i = 0; i < simple_attribute_count; ++i) {
4477 const Attribute& a = aa.GetSimpleAttribute(i);
4481 const GLint index = spr->GetAttributeIndex(spec);
4483 simple_attribute_indices_[i] =
static_cast<GLuint
>(index);
4486 <<
"***ION: Attribute array contains simple attribute '"
4487 << spec->name <<
"' but the current shader program '"
4488 << spr->GetShaderProgram().GetLabel() <<
"' does not"
4489 <<
" declare or use it";
4495 bool Renderer::VertexArrayResource::UpdateAndCheckBuffers(ResourceBinder* rb) {
4496 if (AnyModifiedBitsSet()) {
4497 ScopedResourceLabel
label(
this, rb);
4499 GraphicsManager* gm = GetGraphicsManager();
4501 if (!id_) gm->GenVertexArrays(1, &id_);
4503 const AttributeArray& aa = GetAttributeArray();
4504 DCHECK_EQ(aa.GetBufferAttributeCount(), buffer_attribute_infos_.size());
4505 DCHECK_EQ(aa.GetSimpleAttributeCount(), simple_attribute_indices_.size());
4513 rb->ClearVertexArrayBinding(id_);
4515 rb->BindVertexArray(id_,
this);
4517 const size_t buffer_attribute_count = aa.GetBufferAttributeCount();
4518 DCHECK_EQ(buffer_attribute_count, buffer_attribute_infos_.size());
4519 for (
size_t i = 0; i < buffer_attribute_count; ++i) {
4520 const Attribute& a = aa.GetBufferAttribute(i);
4521 UpdateVertexCount(a);
4522 BufferAttributeInfo& info = buffer_attribute_infos_[i];
4524 if (TestModifiedBit(
4526 !BindBufferObjectElementAttribute(info.index, a, &info.slots, rb))
4529 if (TestModifiedBit(static_cast<int>(
4532 if (aa.IsBufferAttributeEnabled(i)) {
4533 for (GLuint j = 0; j < info.slots; ++j)
4534 gm->EnableVertexAttribArray(info.index + j);
4535 info.enabled =
true;
4537 for (GLuint j = 0; j < info.slots; ++j)
4538 gm->DisableVertexAttribArray(info.index + j);
4539 info.enabled =
false;
4548 ResetModifiedBits();
4550 LOG(
ERROR) <<
"***ION: Unable to create vertex array";
4556 rb->BindVertexArray(id_,
this);
4557 BindSimpleAttributes();
4561 bool Renderer::VertexArrayResource::BindAndCheckBuffers(
bool force_bind,
4562 ResourceBinder* rb) {
4565 if ((UpdateAndCheckBuffers(rb) || force_bind) && id_) {
4566 ScopedResourceLabel
label(
this, rb);
4567 rb->BindVertexArray(id_,
this);
4573 void Renderer::VertexArrayResource::Unbind(ResourceBinder* rb) {
4575 rb->ClearVertexArrayBinding(id_);
4578 void Renderer::VertexArrayResource::Release(
bool can_make_gl_calls) {
4579 BaseResourceType::Release(can_make_gl_calls);
4583 if (resource_owns_gl_id_ && can_make_gl_calls)
4584 GetGraphicsManager()->DeleteVertexArrays(1, &id_);
4597 class Renderer::VertexArrayEmulatorResource
4598 :
public Renderer::VertexArrayResource {
4600 VertexArrayEmulatorResource(ResourceBinder* rb, ResourceManager* rm,
4601 const AttributeArray& attribute_array,
4603 : VertexArrayResource(rb, rm, attribute_array, key, id) {}
4604 ~VertexArrayEmulatorResource()
override {}
4606 void Release(
bool can_make_gl_calls)
override;
4607 bool UpdateAndCheckBuffers(ResourceBinder* rb)
override;
4610 bool BindAndCheckBuffers(
bool force_bind, ResourceBinder* rb)
override;
4611 void Unbind(ResourceBinder* rb)
override;
4614 bool Renderer::VertexArrayEmulatorResource::UpdateAndCheckBuffers(
4615 ResourceBinder* rb) {
4618 if (rb->GetActiveVertexArray() !=
this || AnyModifiedBitsSet()) {
4619 ResetModifiedBits();
4621 ScopedResourceLabel
label(
this, rb);
4622 rb->SetActiveVertexArray(
this);
4623 BindSimpleAttributes();
4626 GraphicsManager* gm = GetGraphicsManager();
4627 const AttributeArray& aa = GetAttributeArray();
4630 const size_t buffer_attribute_count = aa.GetBufferAttributeCount();
4631 DCHECK_EQ(buffer_attribute_count, buffer_attribute_infos_.size());
4632 for (
size_t i = 0; i < buffer_attribute_count; ++i) {
4633 if (aa.IsBufferAttributeEnabled(i)) {
4634 const Attribute& a = aa.GetBufferAttribute(i);
4635 UpdateVertexCount(a);
4636 BufferAttributeInfo& info = buffer_attribute_infos_[i];
4638 if (!BindBufferObjectElementAttribute(info.index, a, &info.slots, rb))
4642 for (GLuint j = 0; j < info.slots; ++j)
4643 gm->EnableVertexAttribArray(info.index);
4644 info.enabled =
true;
4652 bool Renderer::VertexArrayEmulatorResource::BindAndCheckBuffers(
4653 bool force_bind, ResourceBinder* rb) {
4654 return UpdateAndCheckBuffers(rb);
4657 void Renderer::VertexArrayEmulatorResource::Unbind(ResourceBinder* rb) {
4660 if (rb && rb->GetActiveVertexArray() ==
this) {
4661 GraphicsManager* gm = GetGraphicsManager();
4664 const size_t buffer_attribute_count = buffer_attribute_infos_.size();
4665 for (
size_t i = 0; i < buffer_attribute_count; ++i) {
4666 BufferAttributeInfo& info = buffer_attribute_infos_[i];
4669 if (can_make_gl_calls) {
4670 for (GLuint j = 0; j < info.slots; ++j)
4671 gm->DisableVertexAttribArray(info.index);
4674 info.enabled =
false;
4677 rb->SetActiveVertexArray(
nullptr);
4681 void Renderer::VertexArrayEmulatorResource::Release(
bool can_make_gl_calls) {
4682 BaseResourceType::Release(can_make_gl_calls);
4695 : flags_(AllProcessFlags()),
4706 ResourceBinder* resource_binder = GetInternalResourceBinder(&visual_id);
4707 if (visual_id == 0) {
4708 LOG(
WARNING) <<
"***ION: renderer.cc: ~Renderer"
4709 <<
": No Visual ID (invalid GL Context?)";
4711 resource_manager_->DestroyAllResources();
4712 if (resource_binder)
4764 return resource_manager_->GetGraphicsManager();
4768 return resource_manager_.get();
4773 ResourceBinderMap, binders,
4774 new ResourceBinderMap(
4782 const size_t id = visual->
GetId();
4798 Renderer::ResourceBinder* Renderer::GetInternalResourceBinder(
4799 size_t* visual_id)
const {
4803 ResourceBinderMap& binders = GetResourceBinderMap();
4804 ResourceBinderMap::iterator it = binders.find(*visual_id);
4806 if (it == binders.end())
4809 ResourceBinder* rb = it->second.get();
4811 rb->SetResourceManager(resource_manager_.get());
4815 Renderer::ResourceBinder*
4816 Renderer::GetOrCreateInternalResourceBinder(
int line)
const {
4817 size_t visual_id = 0;
4818 ResourceBinder* rb = GetInternalResourceBinder(&visual_id);
4819 if (visual_id == 0) {
4820 LOG(
WARNING) <<
"***ION: renderer.cc:" << line
4821 <<
": No Visual ID (invalid GL Context?)";
4822 DCHECK(!rb) <<
"Unexpected ResourceBinder for visual 0.";
4826 ResourceBinderMap& binders = GetResourceBinderMap();
4828 base::WriteLock write_lock(GetResourceBinderLock());
4830 DCHECK(binders.find(visual_id) == binders.end())
4831 <<
"Two threads tried to create ResourceBinders for the same Visual!";
4832 binders[visual_id].reset(rb);
4835 rb->SetResourceManager(resource_manager_.get());
4840 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4842 if (resource_binder) {
4843 resource_binder->ClearNonFramebufferCachedBindings();
4844 if (!fbo.
Get() || fbo->GetWidth() == 0 || fbo->GetHeight() == 0) {
4845 resource_binder->BindFramebuffer(
4848 FramebufferResource* fbr =
4849 resource_manager_->GetResource(fbo.
Get(), resource_binder);
4851 fbr->Bind(resource_binder);
4853 resource_binder->SetCurrentFramebuffer(fbo);
4858 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4859 return resource_binder ?
4864 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4865 if (resource_binder)
4866 resource_binder->UpdateDefaultFramebufferFromOpenGL();
4870 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4871 if (resource_binder) {
4872 resource_binder->ClearNonFramebufferCachedBindings();
4873 resource_binder->ClearFramebufferBinding(0U);
4877 template <
typename T>
4879 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4880 if (resource_binder)
4881 resource_binder->BindResource(holder);
4885 template ION_API
void Renderer::BindResource<BufferObject>(
4887 template ION_API
void Renderer::BindResource<CubeMapTexture>(
4889 template ION_API
void Renderer::BindResource<FramebufferObject>(
4891 template ION_API
void Renderer::BindResource<IndexBuffer>(
4893 template ION_API
void Renderer::BindResource<Sampler>(
Sampler*);
4894 template ION_API
void Renderer::BindResource<ShaderProgram>(
4896 template ION_API
void Renderer::BindResource<Texture>(
Texture*);
4898 template <
typename T>
4900 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4901 if (resource_binder)
4902 resource_binder->Process<ResourceBinder::CreateOrUpdateOp>(holder, 0U);
4906 template ION_API
void Renderer::CreateOrUpdateResource<AttributeArray>(
4908 template ION_API
void Renderer::CreateOrUpdateResource<BufferObject>(
4910 template ION_API
void Renderer::CreateOrUpdateResource<CubeMapTexture>(
4912 template ION_API
void Renderer::CreateOrUpdateResource<FramebufferObject>(
4914 template ION_API
void Renderer::CreateOrUpdateResource<IndexBuffer>(
4916 template ION_API
void Renderer::CreateOrUpdateResource<Sampler>(
4918 template ION_API
void Renderer::CreateOrUpdateResource<ShaderInputRegistry>(
4920 template ION_API
void Renderer::CreateOrUpdateResource<ShaderProgram>(
4922 template ION_API
void Renderer::CreateOrUpdateResource<Texture>(
4926 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4927 if (resource_binder)
4928 resource_binder->ProcessStateTable(state_table);
4932 ION_API
void Renderer::CreateResourceWithExternallyManagedId<BufferObject>(
4934 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4935 if (resource_binder && resource_binder->GetGraphicsManager()->IsBuffer(gl_id))
4936 resource_binder->Process<ResourceBinder::CreateOrUpdateOp>(holder, gl_id);
4940 ION_API
void Renderer::CreateResourceWithExternallyManagedId<IndexBuffer>(
4942 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4943 if (resource_binder && resource_binder->GetGraphicsManager()->IsBuffer(gl_id))
4944 resource_binder->Process<ResourceBinder::CreateOrUpdateOp>(holder, gl_id);
4948 ION_API
void Renderer::CreateResourceWithExternallyManagedId<Texture>(
4949 Texture* holder, uint32 gl_id) {
4950 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4951 if (resource_binder &&
4952 resource_binder->GetGraphicsManager()->IsTexture(gl_id))
4953 resource_binder->Process<ResourceBinder::CreateOrUpdateOp>(holder, gl_id);
4957 ION_API
void Renderer::CreateResourceWithExternallyManagedId<CubeMapTexture>(
4959 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4960 if (resource_binder &&
4961 resource_binder->GetGraphicsManager()->IsTexture(gl_id))
4962 resource_binder->Process<ResourceBinder::CreateOrUpdateOp>(holder, gl_id);
4966 if (!node.
Get() || !node->IsEnabled())
4969 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
4970 if (resource_binder)
4971 resource_binder->Traverse<ResourceBinder::CreateOrUpdateOp>(node,
4972 default_shader_.
Get());
4975 template <
typename Operation>
4976 void Renderer::ResourceBinder::Traverse(
const NodePtr& node,
4981 ShaderProgram* saved_current_program = current_shader_program_;
4982 ShaderProgramResource* saved_active_resource = active_shader_resource_;
4983 current_shader_program_ = default_shader;
4985 Visit<Operation>(node);
4987 current_shader_program_ = saved_current_program;
4988 active_shader_resource_ = saved_active_resource;
4991 template <
typename Operation>
4992 void Renderer::ResourceBinder::Visit(
const NodePtr& node) {
4993 if (!node.Get() || !node->IsEnabled())
4997 if (ShaderProgram* shader = node->GetShaderProgram().Get()) {
4998 Process<Operation>(shader, 0U);
4999 current_shader_program_ = shader;
5002 active_shader_resource_ = resource_manager_->
GetResource(
5003 current_shader_program_,
this);
5006 const base::AllocVector<Uniform>& uniforms = node->GetUniforms();
5007 const size_t num_uniforms = uniforms.size();
5008 for (
size_t i = 0; i < num_uniforms; ++i) {
5009 Process<Operation>(&uniforms[i].GetRegistry(), 0U);
5011 Process<Operation>(uniforms[i].GetValue<TexturePtr>().Get(), 0U);
5013 Process<Operation>(uniforms[i].GetValue<CubeMapTexturePtr>().Get(), 0U);
5017 const base::AllocVector<UniformBlockPtr>& uniform_blocks =
5018 node->GetUniformBlocks();
5019 const size_t num_uniform_blocks = uniform_blocks.size();
5020 for (
size_t i = 0; i < num_uniform_blocks; ++i) {
5021 if (uniform_blocks[i]->IsEnabled()) {
5022 const base::AllocVector<Uniform>& uniforms =
5023 uniform_blocks[i]->GetUniforms();
5024 const size_t num_uniforms = uniforms.size();
5025 for (
size_t i = 0; i < num_uniforms; ++i) {
5026 Process<Operation>(&uniforms[i].GetRegistry(), 0U);
5028 Process<Operation>(uniforms[i].GetValue<TexturePtr>().Get(), 0U);
5031 uniforms[i].GetValue<CubeMapTexturePtr>().Get(), 0U);
5037 const base::AllocVector<ShapePtr>& shapes = node->GetShapes();
5038 const size_t num_shapes = shapes.size();
5039 for (
size_t i = 0; i < num_shapes; ++i)
5040 VisitShape<Operation>(shapes[i]);
5042 ShaderProgram* saved_program = current_shader_program_;
5045 const base::AllocVector<NodePtr>& children = node->GetChildren();
5046 const size_t num_children = children.size();
5047 for (
size_t i = 0; i < num_children; ++i) {
5048 Visit<Operation>(children[i]);
5049 current_shader_program_ = saved_program;
5053 template <
typename Operation>
5054 void Renderer::ResourceBinder::VisitShape(
const ShapePtr& shape) {
5055 Process<Operation>(shape->GetIndexBuffer().Get(), 0U);
5056 Process<Operation>(shape->GetAttributeArray().Get(), 0U);
5061 ResourceBinder* resource_binder =
5062 GetOrCreateInternalResourceBinder(__LINE__);
5063 if (resource_binder)
5064 resource_binder->VisitShape<ResourceBinder::CreateOrUpdateOp>(shape);
5068 template <
typename T>
5070 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5071 if (resource_binder)
5072 resource_binder->Process<ResourceBinder::RequestUpdateOp>(holder, 0U);
5076 template ION_API
void Renderer::RequestForcedUpdate<AttributeArray>(
5078 template ION_API
void Renderer::RequestForcedUpdate<BufferObject>(
5080 template ION_API
void Renderer::RequestForcedUpdate<CubeMapTexture>(
5082 template ION_API
void Renderer::RequestForcedUpdate<FramebufferObject>(
5084 template ION_API
void Renderer::RequestForcedUpdate<IndexBuffer>(
5086 template ION_API
void Renderer::RequestForcedUpdate<Sampler>(
5088 template ION_API
void Renderer::RequestForcedUpdate<ShaderProgram>(
5090 template ION_API
void Renderer::RequestForcedUpdate<ShaderInputRegistry>(
5092 template ION_API
void Renderer::RequestForcedUpdate<Texture>(
5096 if (!node.
Get() || !node->IsEnabled())
5099 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5100 if (resource_binder)
5101 resource_binder->Traverse<ResourceBinder::RequestUpdateOp>(node,
5102 default_shader_.
Get());
5107 ResourceBinder* resource_binder =
5108 GetOrCreateInternalResourceBinder(__LINE__);
5109 if (resource_binder) {
5110 resource_binder->VisitShape<ResourceBinder::RequestUpdateOp>(shape);
5115 void Renderer::ResourceBinder::ProcessStateTable(
5121 client_state_table_->MergeValuesFrom(*st, *st);
5125 gl_state_table_->MergeNonClearValuesFrom(*st, *st);
5131 ResourceBinder* resource_binder =
5132 GetOrCreateInternalResourceBinder(__LINE__);
5133 if (resource_binder) {
5134 ShaderInputRegistryResource* sirr = resource_manager_->GetResource(
5136 sirr->Update(resource_binder);
5137 sirr->SetInitialValue(u);
5148 !gm->IsFunctionGroupAvailable(
5150 LOG(
WARNING) <<
"No multisampled frambuffer functions available.";
5162 gm->BindFramebuffer(GL_READ_FRAMEBUFFER, ms_fbo_id);
5163 gm->BindFramebuffer(GL_DRAW_FRAMEBUFFER, dest_fbo_id);
5167 gm->BlitFramebuffer(0, 0, ms_fbo->GetWidth(), ms_fbo->GetHeight(), 0, 0,
5168 dest_fbo->GetWidth(), dest_fbo->GetHeight(),
5169 GL_COLOR_BUFFER_BIT, GL_NEAREST);
5170 }
else if (gm->IsFunctionGroupAvailable(
5172 gm->ResolveMultisampleFramebuffer();
5176 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5177 resource_binder->ClearFramebufferBinding(0);
5182 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5183 if (resource_binder) {
5184 resource_binder->DrawScene(node, flags_, default_shader_.
Get());
5187 resource_manager_->ProcessResourceInfoRequests(resource_binder);
5191 void Renderer::ResourceBinder::MarkAttachmentImplicitlyChanged(
5197 Renderer::SetResourceHolderBit(tex,
5202 void Renderer::ResourceBinder::MapBufferObjectDataRange(
5204 BufferObjectDataMapMode mode,
5206 BufferObject* bo = buffer.Get();
5209 if (bo->GetMappedPointer()) {
5210 LOG(
WARNING) <<
"A buffer that is already mapped was passed to"
5214 if (range_in.IsEmpty()) {
5215 LOG(
WARNING) <<
"Ignoring empty range passed to"
5220 0U, static_cast<uint32>(bo->GetStructSize() * bo->GetCount()));
5222 void* data =
nullptr;
5223 BufferObject::MappedBufferData::DataSource data_source =
5224 BufferObject::MappedBufferData::kGpuMapped;
5225 GraphicsManager* gm = GetGraphicsManager().Get();
5228 BufferResource* br = resource_manager_->GetResource(bo,
this);
5231 if (mode == kReadOnly)
5232 access_mode = GL_MAP_READ_BIT;
5233 else if (mode == kWriteOnly)
5234 access_mode = GL_MAP_WRITE_BIT;
5236 access_mode = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
5237 data = gm->MapBufferRange(br->GetGlTarget(), range.GetMinPoint(),
5238 range.GetSize(), access_mode);
5240 range == entire_range) {
5241 BufferResource* br = resource_manager_->GetResource(bo,
this);
5244 if (mode == kReadOnly)
5245 access_mode = GL_READ_ONLY;
5246 else if (mode == kWriteOnly)
5247 access_mode = GL_WRITE_ONLY;
5249 access_mode = GL_READ_WRITE;
5250 data = gm->MapBuffer(br->GetGlTarget(), access_mode);
5251 }
else if (range.GetSize() <= entire_range.GetSize()) {
5253 if (bo->GetData().Get() && bo->GetData()->GetData() &&
5254 bo->GetCount() * bo->GetStructSize() >= range_in.GetMaxPoint()) {
5255 data =
static_cast<void*
>(
5256 bo->GetData()->GetMutableData<uint8>() + range_in.GetMinPoint());
5257 data_source = BufferObject::MappedBufferData::kDataContainer;
5260 data_source = BufferObject::MappedBufferData::kAllocated;
5261 if (mode != kWriteOnly) {
5262 LOG(
WARNING) <<
"MapBufferObjectDataRange() glMapBufferRange not "
5263 "supported and BufferObject's DataContainer has been wiped so "
5264 "mapped bytes are uninitialized, i.e., garbage.";
5269 bo->SetMappedData(range, data, data_source, mode == kReadOnly);
5271 LOG(
ERROR) <<
"Failed to allocate data for "
5275 void Renderer::ResourceBinder::UnmapBufferObjectData(
5277 BufferObject* bo = buffer.Get();
5280 if (
void* ptr = bo->GetMappedPointer()) {
5281 BufferResource* br = resource_manager_->GetResource(bo,
this);
5283 if (bo->GetMappedData().data_source ==
5284 BufferObject::MappedBufferData::kGpuMapped &&
5285 graphics_manager_->IsFunctionGroupAvailable(
5287 graphics_manager_->UnmapBuffer(br->GetGlTarget());
5289 if (!bo->GetMappedData().read_only)
5290 br->UploadSubData(bo->GetMappedData().range, ptr);
5291 if (bo->GetMappedData().data_source ==
5292 BufferObject::MappedBufferData::kAllocated) {
5294 bo->GetAllocator()->DeallocateMemory(ptr);
5301 base::InvalidEnumValue<BufferObject::MappedBufferData::DataSource>(),
5304 LOG(
WARNING) <<
"An unmapped BufferObject was passed to"
5309 void Renderer::ResourceBinder::DrawScene(
const NodePtr& node,
5311 ShaderProgram* default_shader) {
5312 GraphicsManager* gm = GetGraphicsManager().Get();
5315 if ((flags & AllSaveFlags()).any()) {
5317 if (flags.test(kSaveActiveTexture))
5318 gm->GetIntegerv(GL_ACTIVE_TEXTURE, GetSavedId(kSaveActiveTexture));
5319 if (flags.test(kSaveArrayBuffer))
5320 gm->GetIntegerv(GL_ARRAY_BUFFER_BINDING, GetSavedId(kSaveArrayBuffer));
5321 if (flags.test(kSaveElementArrayBuffer))
5322 gm->GetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING,
5323 GetSavedId(kSaveElementArrayBuffer));
5324 if (flags.test(kSaveFramebuffer))
5325 gm->GetIntegerv(GL_FRAMEBUFFER_BINDING, GetSavedId(kSaveFramebuffer));
5326 if (flags.test(kSaveStateTable)) {
5329 const base::IndexMap<StateTable::Capability, GLenum> capability_map =
5330 base::EnumHelper::GetIndexMap<StateTable::Capability>();
5331 const size_t num_capabilities = capability_map.GetCount();
5332 for (
size_t i = 0; i < num_capabilities; ++i) {
5336 if (!saved_state_table_->IsCapabilitySet(st_cap))
5340 if (flags.test(kSaveShaderProgram))
5341 gm->GetIntegerv(GL_CURRENT_PROGRAM, GetSavedId(kSaveShaderProgram));
5342 if (flags.test(kSaveVertexArray) &&
5344 gm->GetIntegerv(GL_VERTEX_ARRAY_BINDING, GetSavedId(kSaveVertexArray));
5348 if (FramebufferResource* fbr = GetActiveFramebuffer()) fbr->Bind(
this);
5351 if (flags.test(kProcessReleases)) resource_manager_->ReleaseAll(
this);
5355 current_shader_program_ = default_shader;
5358 current_traversal_index_ = 0;
5360 DrawNode(*node, gm);
5364 if (FramebufferObject* fbo = GetCurrentFramebuffer().Get()) {
5365 MarkAttachmentImplicitlyChanged(fbo->GetColorAttachment(0U));
5366 MarkAttachmentImplicitlyChanged(fbo->GetDepthAttachment());
5367 MarkAttachmentImplicitlyChanged(fbo->GetStencilAttachment());
5372 if ((flags & (AllRestoreFlags() | AllClearFlags())).any()) {
5374 if (flags.test(kRestoreArrayBuffer))
5377 else if (flags.test(kClearArrayBuffer))
5380 if (flags.test(kRestoreElementArrayBuffer))
5382 *GetSavedId(kSaveElementArrayBuffer),
nullptr);
5383 else if (flags.test(kClearElementArrayBuffer))
5386 if (flags.test(kRestoreFramebuffer)) {
5387 BindFramebuffer(*GetSavedId(kSaveFramebuffer),
nullptr);
5389 }
else if (flags.test(kClearFramebuffer)) {
5390 BindFramebuffer(0U,
nullptr);
5394 if (flags.test(kRestoreShaderProgram))
5395 BindProgram(*GetSavedId(kSaveShaderProgram),
nullptr);
5396 else if (flags.test(kClearShaderProgram))
5397 BindProgram(0U,
nullptr);
5399 if (flags.test(kRestoreStateTable)) {
5401 gl_state_table_->MergeNonClearValuesFrom(*saved_state_table_,
5402 *saved_state_table_);
5406 if (flags.test(kRestoreVertexArray))
5407 BindVertexArray(*GetSavedId(kSaveVertexArray),
nullptr);
5408 else if (flags.test(kClearVertexArray))
5409 BindVertexArray(0U,
nullptr);
5413 if (flags.test(kClearCubemaps)) {
5414 const GLuint count =
static_cast<GLuint
>(image_units_.size());
5415 for (GLuint i = 0; i < count; ++i) {
5417 gm->BindTexture(GL_TEXTURE_CUBE_MAP, 0);
5418 ClearTextureBinding(0U, i);
5420 gm->BindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
5421 ClearTextureBinding(0U, i);
5425 if (flags.test(kClearTextures)) {
5426 const GLuint count =
static_cast<GLuint
>(image_units_.size());
5427 for (GLuint i = 0; i < count; ++i) {
5429 gm->BindTexture(GL_TEXTURE_2D, 0);
5430 ClearTextureBinding(0U, i);
5432 gm->BindTexture(GL_TEXTURE_1D_ARRAY, 0);
5433 gm->BindTexture(GL_TEXTURE_2D_ARRAY, 0);
5434 gm->BindTexture(GL_TEXTURE_3D, 0);
5436 if (gm->IsExtensionSupported(
"image_external")) {
5441 if (flags.test(kClearSamplers)) {
5442 const GLuint count =
static_cast<GLuint
>(image_units_.size());
5443 for (GLuint i = 0; i < count; ++i)
5444 BindSamplerToUnit(0U, i);
5447 if (flags.test(kRestoreActiveTexture))
5448 ActivateUnit(*GetSavedId(kSaveActiveTexture) - GL_TEXTURE0);
5449 else if (flags.test(kClearActiveTexture))
5455 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5456 if (resource_binder)
5457 resource_manager_->ProcessResourceInfoRequests(resource_binder);
5461 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5462 if (resource_binder)
5464 resource_binder->GetStateTable());
5468 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5469 if (resource_binder)
5470 resource_binder->GetStateTable()->CopyFrom(*state_table);
5474 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5475 if (!resource_binder) {
5478 LOG(
WARNING) <<
"***ION: No ResourceBinder (invalid GL Context?): "
5479 <<
" using default StateTable";
5480 return *kDefaultStateTable->Get();
5482 return *resource_binder->GetStateTable();
5490 0U, static_cast<uint32>(bo->GetStructSize() * bo->GetCount()));
5493 LOG(
WARNING) <<
"A NULL BufferObject was passed to"
5502 if (ResourceBinder* resource_binder =
5503 GetOrCreateInternalResourceBinder(__LINE__)) {
5504 resource_binder->MapBufferObjectDataRange(buffer, mode, range_in);
5507 LOG(
WARNING) <<
"A NULL BufferObject was passed to"
5514 if (ResourceBinder* resource_binder =
5515 GetOrCreateInternalResourceBinder(__LINE__)) {
5516 resource_binder->UnmapBufferObjectData(buffer);
5519 LOG(
WARNING) <<
"A NULL BufferObject was passed to"
5527 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5528 return resource_binder ?
5529 resource_binder->ReadImage(range, format, allocator) :
ImagePtr();
5537 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5538 if (resource_binder)
5539 resource_binder->GetStreamAnnotator()->Push(marker);
5542 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5543 if (resource_binder)
5544 resource_binder->GetStreamAnnotator()->Pop();
5548 template <
typename T>
5552 typedef typename HolderToResource<T>::ResourceType
ResourceType;
5553 ResourceBinder* resource_binder =
5554 GetOrCreateInternalResourceBinder(__LINE__);
5555 if (resource_binder) {
5556 resource_binder->BindResource(holder);
5557 ResourceType* resource =
5558 resource_manager_->GetResource(holder, resource_binder);
5559 id = resource->GetId();
5566 template ION_API uint32
5567 Renderer::GetResourceGlId<BufferObject>(
BufferObject*);
5568 template ION_API uint32
5570 template ION_API uint32
5572 template ION_API uint32
5573 Renderer::GetResourceGlId<IndexBuffer>(
IndexBuffer*);
5574 template ION_API uint32 Renderer::GetResourceGlId<Sampler>(
Sampler*);
5575 template ION_API uint32 Renderer::GetResourceGlId<Shader>(
Shader*);
5576 template ION_API uint32
5578 template ION_API uint32 Renderer::GetResourceGlId<Texture>(
Texture*);
5581 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5582 if (resource_binder)
5583 resource_binder->SetImageUnitRange(units);
5586 template <
typename T>
5588 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5589 if (resource_binder)
5590 resource_manager_->ReleaseResources(holder, resource_binder);
5594 template ION_API
void Renderer::ClearResources<AttributeArray>(
5596 template ION_API
void Renderer::ClearResources<BufferObject>(
5598 template ION_API
void Renderer::ClearResources<CubeMapTexture>(
5600 template ION_API
void Renderer::ClearResources<FramebufferObject>(
5602 template ION_API
void Renderer::ClearResources<Sampler>(
const Sampler*);
5603 template ION_API
void Renderer::ClearResources<Shader>(
const Shader*);
5604 template ION_API
void Renderer::ClearResources<ShaderProgram>(
5606 template ION_API
void Renderer::ClearResources<Texture>(
const Texture*);
5610 resource_manager_->ReleaseTypedResources(static_cast<ResourceType>(i));
5615 resource_manager_->ReleaseTypedResources(type);
5620 ResourceBinder* resource_binder = GetOrCreateInternalResourceBinder(__LINE__);
5621 if (resource_binder)
5622 resource_manager_->ReleaseAll(resource_binder);
5626 return resource_manager_->GetGpuMemoryUsage(type);
5631 static const char* kDefaultVertexShaderString =
5632 "uniform mat4 uProjectionMatrix;\n"
5633 "uniform mat4 uModelviewMatrix;\n"
5634 "attribute vec3 aVertex;\n"
5636 "void main(void) {\n"
5637 " gl_Position = uProjectionMatrix * uModelviewMatrix *\n"
5638 " vec4(aVertex, 1.);\n"
5641 static const char* kDefaultFragmentShaderString =
5643 "precision mediump float;\n"
5646 "uniform vec4 uBaseColor;\n"
5648 "void main(void) {\n"
5649 " gl_FragColor = uBaseColor;\n"
5655 empty_registry->IncludeGlobalRegistry();
5658 program->SetLabel(
"Default Renderer shader");
5659 program->SetVertexShader(
5661 program->SetFragmentShader(
5663 program->GetVertexShader()->SetLabel(
"Default Renderer vertex shader");
5664 program->GetFragmentShader()->SetLabel(
"Default Renderer fragment shader");
5668 void Renderer::SetResourceHolderBit(
const ResourceHolder* holder,
int bit) {
5669 holder->OnChanged(bit);
5672 void Renderer::ResourceBinder::DrawNode(
const Node& node, GraphicsManager* gm) {
5673 if (!node.IsEnabled())
5676 ScopedLabel
label(
this, &node, node.GetLabel());
5678 if (
const StateTable* st = node.GetStateTable().Get()) {
5681 traversal_state_tables_[current_traversal_index_]->CopyFrom(
5682 *client_state_table_.Get());
5684 if (++current_traversal_index_ >= traversal_state_tables_.size())
5685 traversal_state_tables_.push_back(
StateTablePtr(
new StateTable));
5688 client_state_table_->MergeValuesFrom(*st, *st);
5690 if (st->AreSettingsEnforced()) {
5693 gl_state_table_->MergeNonClearValuesFrom(*st, *st);
5698 if (ShaderProgram* shader = node.GetShaderProgram().Get())
5699 current_shader_program_ = shader;
5700 DCHECK(current_shader_program_);
5703 PushUniforms(&node, node.GetUniforms());
5704 const base::AllocVector<UniformBlockPtr>& uniform_blocks =
5705 node.GetUniformBlocks();
5706 const size_t num_uniform_blocks = uniform_blocks.size();
5707 for (
size_t i = 0; i < num_uniform_blocks; ++i)
5708 if (uniform_blocks[i]->IsEnabled())
5709 PushUniforms(&node, uniform_blocks[i]->GetUniforms());
5712 const base::AllocVector<ShapePtr>& shapes = node.GetShapes();
5713 if (
const size_t num_shapes = shapes.size()) {
5719 resource_manager_->GetResource(current_shader_program_,
this)->Bind(
this);
5722 for (
size_t i = 0; i < num_shapes; ++i)
5723 DrawShape(*shapes[i], gm);
5726 gl_state_table_->MergeNonClearValuesFrom(*client_state_table_,
5727 *client_state_table_);
5732 ShaderProgram* saved_shader_program = current_shader_program_;
5735 const base::AllocVector<NodePtr>& children = node.GetChildren();
5736 const size_t num_children = children.size();
5737 for (
size_t i = 0; i < num_children; ++i) {
5738 DrawNode(*children[i], gm);
5740 current_shader_program_ = saved_shader_program;
5744 if (
const StateTable* st = node.GetStateTable().Get()) {
5745 --current_traversal_index_;
5746 client_state_table_->MergeNonClearValuesFrom(
5747 *traversal_state_tables_[current_traversal_index_].Get(), *st);
5751 PopUniforms(node.GetUniforms());
5752 for (
size_t i = 0; i < num_uniform_blocks; ++i)
5753 if (uniform_blocks[i]->IsEnabled())
5754 PopUniforms(uniform_blocks[i]->GetUniforms());
5757 void Renderer::ResourceBinder::DrawShape(
const Shape& shape,
5758 GraphicsManager* gm) {
5759 if (!shape.GetAttributeArray().Get())
5761 const AttributeArray& attribute_array = *shape.GetAttributeArray();
5762 if (attribute_array.GetAttributeCount() == 0U ||
5763 (shape.GetIndexBuffer().Get() && !shape.GetIndexBuffer()->GetCount()))
5766 ScopedLabel
label(
this, &shape, shape.GetLabel());
5771 VertexArrayResource* var;
5773 var = resource_manager_->GetResource(&attribute_array,
this);
5775 var = resource_manager_->GetResource(
5776 reinterpret_cast<const AttributeArrayEmulator*>(&attribute_array),
5779 if (var && !var->BindAndCheckBuffers(
false,
this))
5783 if (IndexBuffer* ib = shape.GetIndexBuffer().Get()) {
5784 DrawIndexedShape(shape, *ib, gm);
5786 DrawNonindexedShape(shape, var->GetVertexCount(), gm);
5790 void Renderer::ResourceBinder::DrawIndexedShape(
const Shape& shape,
5791 const IndexBuffer& ib,
5792 GraphicsManager* gm) {
5794 BufferResource* br = resource_manager_->GetResource(&ib,
this);
5801 const BufferObject::Spec& spec = ib.GetSpec(0);
5805 gm->GetGlVersion() < 30 &&
5806 (data_type == GL_INT || data_type == GL_UNSIGNED_INT)) {
5807 LOG(
ERROR) <<
"***ION: Unable to draw shape " << shape.GetLabel()
5808 <<
" using index buffer: "
5809 <<
"The component type is not supported on this platform";
5811 const GLenum prim_type =
5813 if (
const size_t range_count = shape.GetVertexRangeCount()) {
5815 for (
size_t i = 0; i < range_count; ++i) {
5816 if (shape.IsVertexRangeEnabled(i)) {
5817 const Range1i& range = shape.GetVertexRange(i);
5818 const int start_index = range.GetMinPoint()[0];
5819 const int count = range.GetSize();
5821 const int instance_count = shape.GetVertexRangeInstanceCount(i);
5823 if (instance_count &&
5824 gm->IsFunctionGroupAvailable(
5826 gm->DrawElementsInstanced(prim_type, count, data_type,
5827 reinterpret_cast<const GLvoid*>(
5828 start_index * ib.GetStructSize()),
5831 if (instance_count) {
5833 "available. The vertex ranges in Shape: "
5835 <<
" will be drawn only once.";
5837 gm->DrawElements(prim_type, count, data_type,
5838 reinterpret_cast<const GLvoid*>(
5839 start_index * ib.GetStructSize()));
5845 const int instance_count = shape.GetInstanceCount();
5846 if (instance_count &&
5848 gm->DrawElementsInstanced(
5849 prim_type, static_cast<GLsizei>(ib.GetCount()), data_type,
5850 reinterpret_cast<const GLvoid*>(0), instance_count);
5852 if (instance_count) {
5854 <<
"***ION: Instanced drawing is not available. Shape: "
5855 << shape.GetLabel() <<
" will be drawn only once.";
5857 gm->DrawElements(prim_type, static_cast<GLsizei>(ib.GetCount()),
5858 data_type, reinterpret_cast<const GLvoid*>(0));
5863 void Renderer::ResourceBinder::DrawNonindexedShape(
const Shape& shape,
5865 GraphicsManager* gm) {
5866 const GLenum prim_type =
5868 if (
const size_t range_count = shape.GetVertexRangeCount()) {
5870 for (
size_t i = 0; i < range_count; ++i) {
5871 if (shape.IsVertexRangeEnabled(i)) {
5872 const Range1i& range = shape.GetVertexRange(i);
5873 const int start_index = range.GetMinPoint()[0];
5874 const int count = range.GetSize();
5876 const int instance_count = shape.GetVertexRangeInstanceCount(i);
5877 if (instance_count &&
5879 gm->DrawArraysInstanced(prim_type, start_index, count,
5882 if (instance_count) {
5884 "The vertex ranges in Shape: "
5886 <<
" will be drawn only once.";
5888 gm->DrawArrays(prim_type, start_index, count);
5894 const int instance_count = shape.GetInstanceCount();
5895 if (instance_count &&
5897 gm->DrawArraysInstanced(prim_type, 0, static_cast<GLsizei>(vertex_count),
5900 if (instance_count) {
5902 <<
"***ION: Instanced drawing is not available. Shape: "
5903 << shape.GetLabel() <<
" will be drawn only once.";
5905 gm->DrawArrays(prim_type, 0, static_cast<GLsizei>(vertex_count));
5911 GLuint
id, BufferResource* resource) {
5912 if (
id != active_buffers_[target].buffer) {
5913 active_buffers_[target].buffer =
id;
5914 active_buffers_[target].resource = resource;
5917 active_vertex_array_resource_->SetElementArrayBinding(
id, resource);
5921 void Renderer::ResourceBinder::BindFramebuffer(GLuint
id,
5922 FramebufferResource* fbo) {
5923 if (
id != active_framebuffer_) {
5924 DCHECK(!fbo ||
id == fbo->GetId());
5925 active_framebuffer_ =
id;
5926 active_framebuffer_resource_ = fbo;
5927 GetGraphicsManager()->BindFramebuffer(GL_FRAMEBUFFER,
id);
5931 bool Renderer::ResourceBinder::BindProgram(GLuint
id,
5932 ShaderProgramResource* resource) {
5933 if (
id != active_shader_id_) {
5934 DCHECK(!resource ||
id == resource->GetId());
5935 active_shader_id_ =
id;
5936 GetGraphicsManager()->UseProgram(
id);
5937 active_shader_resource_ = resource;
5944 void Renderer::ResourceBinder::BindVertexArray(GLuint
id,
5945 VertexArrayResource* resource) {
5946 if (
id != active_vertex_array_) {
5947 DCHECK(!resource ||
id == resource->GetId());
5948 active_vertex_array_ =
id;
5949 active_vertex_array_resource_ = resource;
5955 GetGraphicsManager()->BindVertexArray(
id);
5959 void Renderer::ResourceBinder::ActivateUnit(GLuint unit) {
5960 DCHECK_LT(unit, static_cast<GLuint>(image_units_.size()));
5961 if (unit != active_image_unit_) {
5962 active_image_unit_ = unit;
5963 GetGraphicsManager()->ActiveTexture(GL_TEXTURE0 + unit);
5967 void Renderer::ResourceBinder::BindTextureToUnit(TextureResource* resource,
5971 TextureResource* current_resource = image_units_[unit].resource;
5972 if (current_resource != resource) {
5976 const GLuint
id = resource->GetId();
5977 const GLenum target = resource->GetGlTarget();
5978 image_units_[unit].resource = resource;
5979 texture_last_bindings_[resource] = unit;
5980 GetGraphicsManager()->BindTexture(target,
id);
5984 void Renderer::ResourceBinder::ClearTextureBinding(GLuint
id, GLuint unit) {
5985 TextureResource*& resource = image_units_[unit].resource;
5986 if (!
id || (resource &&
id == resource->GetId())) {
5991 void Renderer::ResourceBinder::ClearVertexArrayBinding(GLuint
id) {
5992 if (!
id ||
id == active_vertex_array_) {
5993 active_vertex_array_ = 0;
5994 if (active_vertex_array_resource_ &&
5995 active_vertex_array_resource_->GetElementArrayBinding().buffer) {
5998 active_vertex_array_resource_->GetElementArrayBinding().buffer);
6000 active_vertex_array_resource_ =
nullptr;
6004 void Renderer::ResourceBinder::ClearNonFramebufferCachedBindings() {
6007 ClearProgramBinding(0U);
6008 const GLuint count =
static_cast<GLuint
>(GetImageUnitCount());
6009 for (GLuint i = 0U; i < count; ++i) {
6010 ClearTextureBinding(0U, i);
6011 image_units_[i].sampler = 0;
6013 active_image_unit_ =
static_cast<GLuint
>(image_units_.size() + 1U);
6014 ClearVertexArrayBinding(0U);
6017 const ImagePtr Renderer::ResourceBinder::ReadImage(
6021 const int x = range.GetMinPoint()[0];
6022 const int y = range.GetMinPoint()[1];
6023 const int width = range.GetSize()[0];
6024 const int height = range.GetSize()[1];
6026 GraphicsManager* gm = GetGraphicsManager().Get();
6027 Image::PixelFormat pf =
6031 data_size,
nullptr, image->GetAllocator());
6032 memset(data->GetMutableData<uint8>(), 0, data_size);
6034 gm->PixelStorei(GL_PACK_ALIGNMENT, 1);
6035 gm->ReadPixels(x, y, width, height, pf.format, pf.type,
6036 data->GetMutableData<uint8>());
6037 image->Set(format, width, height, data);
6042 void Renderer::ResourceBinder::SendUniform(
const Uniform& uniform,
int location,
6043 GraphicsManager* gm) {
6044 #define SEND_VECTOR_UNIFORM(type, elem_type, num_elements, setter) \
6045 if (uniform.IsArrayOf<type>()) { \
6047 if (uniform.GetCount() > 1) { \
6049 reinterpret_cast<const elem_type*>(&uniform.GetValueAt<type>(1)), \
6050 reinterpret_cast<const elem_type*>(&uniform.GetValueAt<type>(0)) + \
6054 location, static_cast<GLsizei>(uniform.GetCount()), \
6055 reinterpret_cast<const elem_type*>(&uniform.GetValueAt<type>(0))); \
6057 gm->setter(location, 1, \
6058 reinterpret_cast<const elem_type*>(&uniform.GetValue<type>())); \
6061 #define SEND_TEXTURE_UNIFORM(type) \
6063 if (uniform.IsArrayOf<type##Ptr>()) { \
6064 const size_t count = uniform.GetCount(); \
6065 const base::AllocatorPtr& allocator = \
6066 base::AllocationManager::GetDefaultAllocatorForLifetime( \
6067 base::kShortTerm); \
6068 base::AllocVector<GLint> ids(allocator); \
6069 ids.reserve(count); \
6071 for (size_t i = 0; i < count; ++i) \
6072 if (TextureResource* txr = resource_manager_->GetResource( \
6073 uniform.GetValueAt<type##Ptr>(i).Get(), this)) \
6074 ids.push_back(GetLastBoundUnit(txr)); \
6075 gm->Uniform1iv(location, static_cast<GLsizei>(count), &ids[0]); \
6076 } else if (TextureResource* txr = resource_manager_->GetResource( \
6077 uniform.GetValue<type##Ptr>().Get(), this)) { \
6078 gm->Uniform1i(location, GetLastBoundUnit(txr)); \
6084 switch (uniform.GetType()) {
6128 SendMatrixUniform<2>(uniform, gm, location,
6132 SendMatrixUniform<3>(uniform, gm, location,
6133 &GraphicsManager::UniformMatrix3fv);
6136 SendMatrixUniform<4>(uniform, gm, location,
6140 #if !defined(ION_COVERAGE) // COV_NF_START
6144 #endif // COV_NF_END
6146 #undef SEND_VECTOR_UNIFORM
6147 #undef SEND_TEXTURE_UNIFORM
6150 void Renderer::ResourceManager::DisassociateElementBufferFromArrays(
6151 BufferResource* resource) {
6152 ResourceAccessor accessor(resources_[kAttributeArray]);
6153 ResourceVector& resources = accessor.GetResources();
6154 const size_t count = resources.size();
6155 for (
size_t i = 0; i < count; ++i) {
6156 VertexArrayResource* res =
6157 reinterpret_cast<VertexArrayResource*
>(resources[i]);
6158 if (res->GetElementArrayBinding().resource == resource)
6159 res->SetElementArrayBinding(0,
nullptr);
6163 void Renderer::ResourceBinder::PushUniforms(
6164 const Node* node,
const base::AllocVector<Uniform>& uniforms) {
6165 const size_t num_uniforms = uniforms.size();
6166 for (
size_t i = 0; i < num_uniforms; ++i) {
6167 ShaderInputRegistryResource* sirr =
6168 resource_manager_->GetResource(&uniforms[i].GetRegistry(),
this);
6170 sirr->PushUniform(uniforms[i]);
6174 void Renderer::ResourceBinder::PopUniforms(
6175 const base::AllocVector<Uniform>& uniforms) {
6176 const size_t num_uniforms = uniforms.size();
6177 for (
size_t i = 0; i < num_uniforms; ++i) {
6178 ShaderInputRegistryResource* sirr =
6179 resource_manager_->GetResource(&uniforms[i].GetRegistry(),
this);
6180 sirr->PopUniform(uniforms[i]);
6184 template <
typename HolderType>
6185 typename Renderer::HolderToResource<HolderType>::ResourceType*
6186 Renderer::ResourceManager::CreateResource(
const HolderType* holder,
6187 Renderer::ResourceBinder* binder,
6189 typedef typename HolderToResource<HolderType>::ResourceType ResourceType;
6192 holder->GetAllocator().Get() ? holder->GetAllocator()
6194 ResourceType* new_resource =
6195 new (allocator) ResourceType(binder,
this, *holder, key, gl_id);
6196 AddResource(new_resource);
6197 return new_resource;
6200 template <
typename HolderType>
6201 typename Renderer::HolderToResource<HolderType>::ResourceType*
6202 Renderer::ResourceManager::GetResource(
6203 const HolderType* holder, Renderer::ResourceBinder* resource_binder,
6205 typedef typename HolderToResource<HolderType>::ResourceType ResourceType;
6208 ResourceType* resource =
nullptr;
6214 GetResourceKey<ResourceType>(resource_binder, holder);
6215 if (Resource* holder_resource =
6216 static_cast<Resource*>(holder->GetResource(resource_index_, key))) {
6217 resource =
static_cast<ResourceType*
>(holder_resource);
6220 resource = CreateResource(holder, resource_binder, key, gl_id);
6221 holder->SetResource(resource_index_, key, resource);
6229 void Renderer::ResourceManager::FillDataFromRenderer(GLuint
id,
6230 PlatformInfo* info) {}
6233 void Renderer::ResourceManager::FillDataFromRenderer(GLuint
id,
6234 TextureImageInfo* info) {
6236 ResourceAccessor accessor(resources_[kTexture]);
6237 ResourceVector& resources = accessor.GetResources();
6238 if (
const size_t count = resources.size()) {
6239 for (
size_t i = 0; i < count; ++i) {
6240 TextureResource* tr =
reinterpret_cast<TextureResource*
>(resources[i]);
6241 if (static_cast<GLuint>(tr->GetId()) ==
id) {
6243 info->texture.Reset(
6244 const_cast<TextureBase*>(&tr->GetTexture<TextureBase>()));
6246 const CubeMapTexture& tex = tr->GetTexture<CubeMapTexture>();
6247 for (
int f = 0; f < 6; ++f) {
6248 info->images.push_back(GetCubeMapTextureImageOrMipmap(
6249 tex, static_cast<CubeMapTexture::CubeFace>(f)));
6252 const Texture& tex = tr->GetTexture<Texture>();
6253 info->images.push_back(GetTextureImageOrMipmap(tex));
6262 void Renderer::ResourceManager::FillInfoFromResource(
6263 ArrayInfo* info, VertexArrayResource* resource, ResourceBinder* rb) {
6264 info->vertex_count = resource->GetVertexCount();
6268 void Renderer::ResourceManager::FillInfoFromResource(BufferInfo* info,
6269 BufferResource* resource,
6270 ResourceBinder* rb) {
6271 info->target = resource->GetGlTarget();
6275 void Renderer::ResourceManager::FillInfoFromResource(
6276 FramebufferInfo* info, FramebufferResource* resource, ResourceBinder* rb) {
6277 info->color0_renderbuffer.id = resource->GetColor0Id();
6278 info->depth_renderbuffer.id = resource->GetDepthId();
6279 info->stencil_renderbuffer.id = resource->GetStencilId();
6283 void Renderer::ResourceManager::FillInfoFromResource(
6284 ProgramInfo* info, ShaderProgramResource* resource, ResourceBinder* rb) {
6285 if (ShaderResource* shader = resource->GetVertexResource())
6286 info->vertex_shader = shader->GetId();
6287 if (ShaderResource* shader = resource->GetFragmentResource())
6288 info->fragment_shader = shader->GetId();
6292 void Renderer::ResourceManager::FillInfoFromResource(
6293 TextureInfo* info, TextureResource* resource, ResourceBinder* rb) {
6294 info->unit = GL_TEXTURE0 + rb->GetLastBoundUnit(resource);
6295 info->target = resource->GetGlTarget();
6297 resource->GetTexture<TextureBase>().GetTextureType();
6298 info->width = info->height = 0U;
6299 info->format = base::InvalidEnumValue<Image::Format>();
6300 Image* image =
nullptr;
6302 const Texture& tex = resource->GetTexture<Texture>();
6303 if (tex.HasImage(0U))
6304 image = tex.GetImage(0U).Get();
6306 const CubeMapTexture& tex = resource->GetTexture<CubeMapTexture>();
6311 info->format = image->GetFormat();
6312 info->width = image->GetWidth();
6313 info->height = image->GetHeight();
6318 template Renderer::BufferResource* Renderer::ResourceManager::GetResource(
6319 const BufferObject*, Renderer::ResourceBinder*, GLuint);
6320 template Renderer::TextureResource* Renderer::ResourceManager::GetResource(
6321 const CubeMapTexture*, Renderer::ResourceBinder*, GLuint);
6322 template Renderer::FramebufferResource* Renderer::ResourceManager::GetResource(
6323 const FramebufferObject*, Renderer::ResourceBinder*, GLuint);
6324 template Renderer::SamplerResource* Renderer::ResourceManager::GetResource(
6325 const Sampler*, Renderer::ResourceBinder*, GLuint);
6326 template Renderer::ShaderResource* Renderer::ResourceManager::GetResource(
6327 const Shader*, Renderer::ResourceBinder*, GLuint);
6328 template Renderer::ShaderProgramResource*
6329 Renderer::ResourceManager::GetResource(
const ShaderProgram*,
6330 Renderer::ResourceBinder*, GLuint);
6331 template Renderer::TextureResource* Renderer::ResourceManager::GetResource(
6332 const Texture*, Renderer::ResourceBinder*, GLuint);
6333 template Renderer::VertexArrayResource* Renderer::ResourceManager::GetResource(
6334 const AttributeArray*, Renderer::ResourceBinder*, GLuint);
GraphicsManager manages the graphics library for an application.
bool IsInvalidReference(const T &value)
IsInvalidReference() returns true if a passed const reference of type T has an address of InvalidRefe...
const StateTable & GetStateTable() const
Returns the StateTable that the Renderer believes to represent the current state of OpenGL...
kShortTerm is used for objects that are very transient in nature, such as scratch memory used to comp...
virtual void DrawScene(const NodePtr &node)
Draws the scene rooted by the given node into the currently bound framebuffer.
This is used for Apple devices running pre-es-3.0 device with the APPLE_framebuffer_multisample exten...
const AllocationTrackerPtr & GetTracker() const
static uint32 GetConstant(EnumType e)
Returns the constant value corresponding to an enum.
Matrix< 4, float > Matrix4f
base::ReferentPtr< Node >::Type NodePtr
base::ReferentPtr< FramebufferObject >::Type FramebufferObjectPtr
Convenience typedef for shared pointer to a FramebufferObject.
void ClearFromStateTable(const StateTable &new_state, StateTable *save_state, GraphicsManager *gm)
This internal function can be used to update the Clear()-related OpenGL state (dithering, scissor test, write masks, scissor box, and clear values) managed by a GraphicsManager to match a StateTable, and updates save_state to contain the new state.
#define SEND_TEXTURE_UNIFORM(type)
A Texture object represents the image data and mipmaps associated with a single texture.
framebuffer alpha dfactor const GLvoid usage alpha const GLvoid data border const GLuint buffers const GLuint renderbuffers count renderbuffer GLuint framebuffers GLsizei GLint GLenum GLchar name GLsizei GLuint shaders GLint data GLsizei GLchar info_log GLint params GLint GLint precision GLint params GLint params GLint params GLfloat params GLvoid pointer height height const GLchar const GLint length mask dppass param param const GLvoid data const GLint1 value const GLfloat2 value v2 v2 v3 v3 const GLmatrix2 value UniformMatrix4fv
Format
Supported image formats.
#define ION_DECLARE_SAFE_STATIC_POINTER(type, variable)
Declare a static non-array pointer and calls a default constructor.
T Log2(T n)
Returns the base-2 logarithm of n.
CompareMode
Texture comparison modes for depth textures.
Flag
The below flags determine what operations will be performed in a call to DrawScene().
This class can be used in place of std::unordered_map to allow an Ion Allocator to be used for memory...
base::ReferentPtr< Image >::Type ImagePtr
#define ION_DECLARE_SAFE_STATIC_POINTER_WITH_CONSTRUCTOR(type, variable, constructor)
Declare a static non-array pointer and calls a non-default constructor.
ResourceManager(const GraphicsManagerPtr &gm)
A valid GraphicsManagerPtr must be passed to the constructor.
const CubeMapTexturePtr & GetCubeMapTexture() const
Gets the cubemap of the attachment, if any.
SharedPtr< AllocationSizeTracker > AllocationSizeTrackerPtr
Convenience typedef for shared pointer to a AllocationSizeTracker.
base::ReferentPtr< Shape >::Type ShapePtr
Convenience typedef for shared pointer to a Shape.
static size_t GetCurrentId()
Returns a unique ID for the currently bound Visual.
An IndexBuffer is a type of BufferObject that contains the element indices of an array, e.g., a vertex index array.
Range< 1, int32 > Range1i
Process any outstanding requests for information about internal resources that have been made through...
A ShaderProgram represents an OpenGL shader program that can be applied to shapes.
static const Visual * GetCurrent()
Returns the Visual that is current for the calling thread.
ResourceType
The types of resources created by the renderer.
const size_t kInvalidIndex
kInvalidIndex is a size_t value that is very unlikely to be a valid index.
void ClearAllResources()
Immediately clears all internal resources of the Renderer.
static void DestroyCurrentStateCache()
Destroys the internal state cache associated with the current Visual or GL context.
GenericLockGuard< port::Mutex > LockGuard
Convenient typedefs for ion::port::Mutex.
#define SEND_VECTOR_UNIFORM(type, elem_type, num_elements, setter)
void ProcessStateTable(const StateTablePtr &state_table)
Immediately updates OpenGL state with the settings in the passed StateTable.
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
static const Flags & AllFlags()
Convenience functions that return std::bitsets of Flags.
framebuffer alpha dfactor const GLvoid usage alpha const GLvoid data border const GLuint buffers const GLuint renderbuffers count renderbuffer GLuint framebuffers GLsizei GLint GLenum GLchar name GLsizei GLuint shaders GLint data GLsizei GLchar info_log GLint params GLint GLint precision GLint params GLint params GLint params GLfloat params GLvoid pointer height height const GLchar const GLint length mask dppass param param const GLvoid data const GLint1 value const GLfloat2 value v2 v2 v3 v3 UniformMatrix2fv
Matrix< 3, float > Matrix3f
base::ReferentPtr< CubeMapTexture >::Type CubeMapTexturePtr
Convenience typedef for shared pointer to a CubeMapTexture.
const GraphicsManagerPtr & GetGraphicsManager() const
Functions.
const TexturePtr & GetTexture() const
Gets the texture of the attachment, if any.
Whether to query OpenGL for current states and save them, which can be restored using the above kRest...
CubeFace
The names of faces of the cube map.
#define DCHECK_GT(val1, val2)
void ProcessResourceInfoRequests()
Process any outstanding requests for information about internal resources that have been made through...
static const Flags & AllProcessFlags()
virtual const AllocatorPtr & GetAllocatorForLifetime(AllocationLifetime lifetime) const
Returns the correct Allocator to use to allocate memory with a specific lifetime. ...
~Renderer() override
The destructor is protected because all base::Referent classes must have protected or private destruc...
void UpdateStateFromOpenGL(int window_width, int window_height)
A Renderer manages graphics state using a StateTable.
Capability
Enumerated types for StateTable items.
void ResolveMultisampleFramebuffer(const FramebufferObjectPtr &ms_fbo, const FramebufferObjectPtr &dest_fbo)
Resolve a multisampled framebuffer 'ms_fbo' into a single sampled framebuffer 'dest_fbo'.
Range< 2, int32 > Range2i
WrapMode
Texture filter modes.
A FramebufferObject describes an off-screen framebuffer that can be drawn to and read from like a reg...
Range< 1, uint32 > Range1ui
base::ReferentPtr< StateTable >::Type StateTablePtr
Convenience typedef for shared pointer to a StateTable.
SharedPtr< Allocator > AllocatorPtr
Whether to restore certain GL state types when drawing is finished.
void RequestForcedUpdate(T *holder)
Mark an object for a forced update of GL resources.
static void DestroyStateCache(const portgfx::Visual *visual)
Destroys the internal state cache associated with the passed Visual.
const ResourceHolder * GetHolder() const
Retrieve the holder for which this resource was created.
const AllocatorPtr & GetAllocatorForLifetime(AllocationLifetime lifetime) const
Convenience function that returns the Allocator to use to allocate an object with a specific lifetime...
static const Flags & AllRestoreFlags()
static size_t ComputeDataSize(Format format, uint32 width, uint32 height)
Convenience functions that return the correct data size in bytes of an image having the given format ...
void UpdateStateTable(int default_width, int default_height, GraphicsManager *gm, StateTable *st)
Public functions.
T * Get() const
Returns a raw pointer to the instance, which may be NULL.
A LockGuard locks a mutex when created, and unlocks it when destroyed.
void ClearTypedResources(ResourceType type)
Immediately clears the internal resources of all ResourceHolders of the passed type.
std::string ValueToString(const T &val)
ValueToString.
std::bitset< kNumFlags > Flags
A BufferObject describes a generic array of data used, for example, to describe the vertices in a Sha...
Release any internal resources that have been marked for destruction, including OpenGL objects...
static const Flags & AllSaveFlags()
void FillInfoFromOpenGL(InfoType *info)
Performs OpenGL calls to fill in info details, specialized for each type derived from ResourceInfo...
static const PixelFormat & GetPixelFormat(Format format)
Convenience function that returns a PixelFormat given a Format.
void ClearResources(const HolderType *holder)
Immediately clears the internal resources of the passed ResourceHolder.
const GraphicsManagerPtr & GetGraphicsManager() const
Returns the GraphicsManager passed to the constructor.
These are necessary since each column of a matrix must be sent to OpenGL separately and we must know ...
void UnmapBufferObjectData(const BufferObjectPtr &buffer)
Unmaps a previously mapped BufferObject and makes the data available to the graphics hardware...
void PopDebugMarker()
In non-production builds, pops a label off of the Renderer's tracing stream marker stack...
The entries between kAttributeChanged and kAttributeEnabledChanged are reserved for determining which...
void SetConcurrent(bool value)
Sets/returns whether this shader program should have per-thread state.
static const char * GetString(EnumType e)
Returns a string corresponding to an enum.
BufferObjectDataMapMode
The possible ways a BufferObject's data can be mapped.
Allocatable()
This constructor sets up the Allocator pointer.
void BindResource(T *holder)
Immediately creates internal GL resources for the passed holder, uploading any data and binding the r...
const FramebufferObjectPtr GetCurrentFramebuffer() const
Returns the currently bound FramebufferObject.
An AttributeArray represents a collection of Attributes used to describe the vertices of a Shape...
void CreateOrUpdateResource(T *holder)
This function is useful for uploading data to the hardware at a time convenient to the caller when us...
ComponentType
The type of the components of a spec.
void SetInitialUniformValue(const Uniform &u)
Sets the initial value of a Uniform to the passed value.
const Grid & image
The original monochrome image data, as doubles (0 - 1).
#define DCHECK_GE(val1, val2)
base::ReferentPtr< Shader >::Type ShaderPtr
Convenience typedef for shared pointers to Shaders.
#define LOG_ONCE(severity)
Logs the streamed message once per process run with a severity of severity.
void RequestForcedShapeUpdates(const ShapePtr &shape)
Mark a shape's resources for a forced update the next time CreateOrUpdateResources or DrawScene is ca...
EnumType InvalidEnumValue()
InvalidEnumValue() returns an invalid enum value, assuming that -1 is not a valid value...
This covers both OES_EGL_image and OES_EGL_image_external.
GenericLockGuard< ReadLock > ReadGuard
Convenient typedefs for ReadWriteLock.
size_t GetId() const
Returns the ID associated with this Visual.
static const Flags & AllClearFlags()
ResourceKey GetKey() const
Retrieve a key that disambiguates between multiple resources created for the same holder by the same ...
Whether to clear (set to 0) certain GL objects when drawing is finished.
A ResourceManager is an interface for getting information about a Renderer's internal resources...
size_t GetGpuMemoryUsage(ResourceType type) const
Returns the amount of GPU memory used by the passed resource type.
Copyright 2016 Google Inc.
uint32 GetResourceGlId(T *holder)
Returns the OpenGL ID for the passed resource.
const std::string indent_
void RequestForcedUpdates(const NodePtr &node)
Mark the passed object and its descendants for a forced resource update the next time CreateOrUpdateR...
Opaque class that sets up an offscreen OpenGL context/surface/visual in a platform-specific way to al...
Matrix< 2, float > Matrix2f
Dimension- and type-specific typedefs.
static int GetNumComponentsForFormat(Format format)
Convenience function that returns the number of components for a given format.
A WriteLock obtains a write lock, but has a similar interface to a Mutex and can be used with a Write...
void UpdateFromStateTable(const StateTable &new_state, StateTable *save_state, GraphicsManager *gm)
This internal function can be used to update the OpenGL state managed by a GraphicsManager to match a...
#define DCHECK_EQ(val1, val2)
TexturePtr texture
The Texture to add sub-image data to.
ResourceBase * GetResource(size_t index, ResourceKey key) const
Returns the Resource at the given index and key, or NULL if no resource was previously set at that lo...
void SetTextureImageUnitRange(const math::Range1i &units)
Sets the inclusive range of texture image units that the Renderer should use.
#define ION_PRETTY_FUNCTION
Make ION_PRETTY_FUNCTION available on all platforms.
base::ReferentPtr< GraphicsManager >::Type GraphicsManagerPtr
Convenience typedef for shared pointer to a GraphicsManager.
A CubeMapTexture object represents the image data and mipmaps associated with the six faces of a cube...
void CreateOrUpdateShapeResources(const ShapePtr &shape)
Creates or updates any resources necessary to draw the passed Shape, i.e., buffer data is uploaded...
#define DCHECK_LE(val1, val2)
bool IsPowerOfTwo(int value)
Returns true if a value is a power of two.
virtual AllocationSizeTrackerPtr GetGpuTracker()=0
intptr_t ResourceKey
Type of identifiers used to disambiguate between multiple resources created for the same Ion object b...
static bool ExpectedDimensionsForMipmap(const uint32 mipmap_width, const uint32 mipmap_height, const uint32 mipmap_level, const uint32 base_width, const uint32 base_height, uint32 *expected_width, uint32 *expected_height)
Tests mipmap dimensions to see that they are proportional and in range with respect to base_width and...
A Shader represents an OpenGL shader stage.
void * AllocateMemory(size_t size)
Allocates memory of the given size.
base::ReferentPtr< ShaderInputRegistry >::Type ShaderInputRegistryPtr
Convenience typedef for shared pointer to a ShaderInputRegistry.
void BindFramebuffer(const FramebufferObjectPtr &fbo)
Binds the passed FramebufferObject; all future calls to DrawScene() will be drawn into it...
void CreateOrUpdateResources(const NodePtr &node)
Traverses the scene rooted by the given node and creates or updates resources for ShaderPrograms...
void ReleaseResources()
Immediately releases all internal resources of the Renderer which are pending release.
const ImagePtr ReadImage(const math::Range2i &range, Image::Format format, const base::AllocatorPtr &allocator)
Returns an image of the specified format that contains the contents of the hardware framebuffer...
void MapBufferObjectDataRange(const BufferObjectPtr &buffer, BufferObjectDataMapMode mode, const math::Range1ui &range)
This function maps a DataContainer with the size of the passed range.
bool IsConcurrent() const
A ReadLock obtains a read lock, but has a similar interface to a Mutex and can be used with a ReadGua...
base::ReferentPtr< DataContainer >::Type DataContainerPtr
These are only usable with the minification filter.
base::ReferentPtr< BufferObject >::Type BufferObjectPtr
Convenience typedef for shared pointer to a BufferObject.
A StateTable represents a collection of graphical state items that affect OpenGL rendering.
gfx::ResourceManager * GetResourceManager() const
Returns the ResourceManager for this renderer.
port::Mutex mutex_
Protects shared access to the Allocator and FT_Library.
An attachment represents a data store attached to one of the framebuffer's targets.
kMipmapChanged must be last since it is a range of slots.
const AllocatorPtr & GetAllocator() const
Returns the Allocator that was used for the instance.
kLongTerm is used for objects that have persistent lifetimes, such as managers.
void PushDebugMarker(const std::string &marker)
In non-production builds, pushes marker onto the Renderer's tracing stream marker stack...
void MapBufferObjectData(const BufferObjectPtr &buffer, BufferObjectDataMapMode mode)
In the below MapBuffer functions the passed BufferObject is assigned a DataContainer (retrievable via...
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
kMediumTerm is used for objects that don't fall into the kShortTerm or kLongTerm categories.
Renderer(const GraphicsManagerPtr &gm)
The constructor is passed a GraphicsManager instance to use for rendering.
void UpdateDefaultFramebufferFromOpenGL()
Updates the system default framebuffer to whatever framebuffer is currently bound.
ResourceBase(const ResourceHolder *holder, ResourceKey key)
The constructor accepts a holder parameter to simplify control flow during construction.
FilterMode
Texture filter modes.
GenericLockGuard< WriteLock > WriteGuard
Matrix< Dimension, T > Transpose(const Matrix< Dimension, T > &m)
Public functions.
void operator=(const Allocatable &other)
The assignment operator does nothing, since all members are intrinsically tied to a particular alloca...
ResourceHolder is an internal base class for objects that hold resources managed by an outside entity...
base::ReferentPtr< Texture >::Type TexturePtr
Convenience typedef for shared pointer to a Texture.
#define DCHECK_LT(val1, val2)
static const int kNumResourceTypes
static const AllocatorPtr & GetDefaultAllocatorForLifetime(AllocationLifetime lifetime)
A Sampler object represents texture parameters that control how texture data is accessed in shaders...
CompareFunction
Texture comparison functions for depth textures.
void ClearCachedBindings()
Notifies the Renderer that it cannot rely on internally cached bindings; the next objects it encounte...
void UpdateStateFromStateTable(const StateTablePtr &state_to_clear)
This is more efficient than UpdateStateFromOpenGL().