blob: 1f9ca3e01b5dd04fa556316b2b0d3022a2b67ea2 [file] [log] [blame]
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/service/sampler_manager.h"
#include "base/bind.h"
#include "base/logging.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/service/error_state.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_fence.h"
#include "ui/gl/gpu_timing.h"
namespace gpu {
namespace gles2 {
SamplerState::SamplerState()
: min_filter(GL_NEAREST_MIPMAP_LINEAR),
mag_filter(GL_LINEAR),
wrap_r(GL_REPEAT),
wrap_s(GL_REPEAT),
wrap_t(GL_REPEAT),
compare_func(GL_LEQUAL),
compare_mode(GL_NONE),
max_lod(1000.0f),
min_lod(-1000.0f) {
}
Sampler::Sampler(SamplerManager* manager, GLuint client_id, GLuint service_id)
: manager_(manager),
client_id_(client_id),
service_id_(service_id),
deleted_(false) {
DCHECK(manager);
}
Sampler::~Sampler() {
if (manager_->have_context_) {
glDeleteSamplers(1, &service_id_);
}
}
GLenum Sampler::SetParameteri(
const FeatureInfo* feature_info, GLenum pname, GLint param) {
DCHECK(feature_info);
switch (pname) {
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD: {
GLfloat fparam = static_cast<GLfloat>(param);
return SetParameterf(feature_info, pname, fparam);
}
case GL_TEXTURE_MIN_FILTER:
if (!feature_info->validators()->texture_min_filter_mode.IsValid(param)) {
return GL_INVALID_ENUM;
}
sampler_state_.min_filter = param;
break;
case GL_TEXTURE_MAG_FILTER:
if (!feature_info->validators()->texture_mag_filter_mode.IsValid(param)) {
return GL_INVALID_ENUM;
}
sampler_state_.mag_filter = param;
break;
case GL_TEXTURE_WRAP_R:
if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
return GL_INVALID_ENUM;
}
sampler_state_.wrap_r = param;
break;
case GL_TEXTURE_WRAP_S:
if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
return GL_INVALID_ENUM;
}
sampler_state_.wrap_s = param;
break;
case GL_TEXTURE_WRAP_T:
if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
return GL_INVALID_ENUM;
}
sampler_state_.wrap_t = param;
break;
case GL_TEXTURE_COMPARE_FUNC:
if (!feature_info->validators()->texture_compare_func.IsValid(param)) {
return GL_INVALID_ENUM;
}
sampler_state_.compare_func = param;
break;
case GL_TEXTURE_COMPARE_MODE:
if (!feature_info->validators()->texture_compare_mode.IsValid(param)) {
return GL_INVALID_ENUM;
}
sampler_state_.compare_mode = param;
break;
default:
return GL_INVALID_ENUM;
}
return GL_NO_ERROR;
}
GLenum Sampler::SetParameterf(
const FeatureInfo* feature_info, GLenum pname, GLfloat param) {
switch (pname) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_WRAP_R:
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_COMPARE_FUNC:
case GL_TEXTURE_COMPARE_MODE: {
GLint iparam = static_cast<GLint>(std::round(param));
return SetParameteri(feature_info, pname, iparam);
}
case GL_TEXTURE_MIN_LOD:
sampler_state_.min_lod = param;
break;
case GL_TEXTURE_MAX_LOD:
sampler_state_.max_lod = param;
break;
default:
return GL_INVALID_ENUM;
}
return GL_NO_ERROR;
}
SamplerManager::SamplerManager(FeatureInfo* feature_info)
: feature_info_(feature_info),
have_context_(true) {
}
SamplerManager::~SamplerManager() {
DCHECK(samplers_.empty());
}
void SamplerManager::Destroy(bool have_context) {
have_context_ = have_context;
while (!samplers_.empty()) {
Sampler* sampler = samplers_.begin()->second.get();
sampler->MarkAsDeleted();
samplers_.erase(samplers_.begin());
}
}
Sampler* SamplerManager::CreateSampler(GLuint client_id, GLuint service_id) {
DCHECK_NE(0u, service_id);
auto result = samplers_.insert(std::make_pair(client_id,
scoped_refptr<Sampler>(new Sampler(this, client_id, service_id))));
DCHECK(result.second);
return result.first->second.get();
}
Sampler* SamplerManager::GetSampler(GLuint client_id) {
SamplerMap::iterator it = samplers_.find(client_id);
return it != samplers_.end() ? it->second.get() : nullptr;
}
void SamplerManager::RemoveSampler(GLuint client_id) {
SamplerMap::iterator it = samplers_.find(client_id);
if (it != samplers_.end()) {
Sampler* sampler = it->second.get();
sampler->MarkAsDeleted();
samplers_.erase(it);
}
}
void SamplerManager::SetParameteri(
const char* function_name, ErrorState* error_state,
Sampler* sampler, GLenum pname, GLint param) {
DCHECK(error_state);
DCHECK(sampler);
GLenum result = sampler->SetParameteri(feature_info_.get(), pname, param);
if (result != GL_NO_ERROR) {
if (result == GL_INVALID_ENUM) {
ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
error_state, function_name, param, "param");
} else {
ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
error_state, result, function_name, pname, param);
}
} else {
glSamplerParameteri(sampler->service_id(), pname, param);
}
}
void SamplerManager::SetParameterf(
const char* function_name, ErrorState* error_state,
Sampler* sampler, GLenum pname, GLfloat param) {
DCHECK(error_state);
DCHECK(sampler);
GLenum result = sampler->SetParameterf(feature_info_.get(), pname, param);
if (result != GL_NO_ERROR) {
if (result == GL_INVALID_ENUM) {
ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
error_state, function_name, param, "param");
} else {
ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
error_state, result, function_name, pname, param);
}
} else {
glSamplerParameterf(sampler->service_id(), pname, param);
}
}
} // namespace gles2
} // namespace gpu