1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gpu/command_buffer/service/abstract_texture_impl_shared_context_state.h"
6
7 #include <utility>
8
9 #include "gpu/command_buffer/service/context_state.h"
10 #include "gpu/command_buffer/service/texture_manager.h"
11 #include "ui/gl/gl_context.h"
12 #include "ui/gl/gl_surface.h"
13 #include "ui/gl/scoped_binders.h"
14 #include "ui/gl/scoped_make_current.h"
15
16 namespace gpu {
17 namespace gles2 {
18
AbstractTextureImplOnSharedContext(GLenum target,GLenum internal_format,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,scoped_refptr<gpu::SharedContextState> shared_context_state)19 AbstractTextureImplOnSharedContext::AbstractTextureImplOnSharedContext(
20 GLenum target,
21 GLenum internal_format,
22 GLsizei width,
23 GLsizei height,
24 GLsizei depth,
25 GLint border,
26 GLenum format,
27 GLenum type,
28 scoped_refptr<gpu::SharedContextState> shared_context_state)
29 : shared_context_state_(std::move(shared_context_state)) {
30 DCHECK(shared_context_state_);
31
32 // The calling code which wants to create this abstract texture should have
33 // already made the shared context current.
34 DCHECK(shared_context_state_->IsCurrent(nullptr));
35
36 // Create a gles2 Texture.
37 GLuint service_id = 0;
38 auto* api = gl::g_current_gl_context;
39 api->glGenTexturesFn(1, &service_id);
40 gl::ScopedTextureBinder binder(target, service_id);
41 api->glTexParameteriFn(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
42 api->glTexParameteriFn(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
43 api->glTexParameteriFn(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
44 api->glTexParameteriFn(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
45
46 texture_ = new gpu::gles2::Texture(service_id);
47 texture_->SetLightweightRef();
48 texture_->SetTarget(target, 1);
49 texture_->set_min_filter(GL_LINEAR);
50 texture_->set_mag_filter(GL_LINEAR);
51 texture_->set_wrap_t(GL_CLAMP_TO_EDGE);
52 texture_->set_wrap_s(GL_CLAMP_TO_EDGE);
53 gfx::Rect cleared_rect;
54 texture_->SetLevelInfo(target, 0, internal_format, width, height, depth,
55 border, format, type, cleared_rect);
56 texture_->SetImmutable(true, false);
57 shared_context_state_->AddContextLostObserver(this);
58 }
59
~AbstractTextureImplOnSharedContext()60 AbstractTextureImplOnSharedContext::~AbstractTextureImplOnSharedContext() {
61 bool have_context = true;
62 base::Optional<ui::ScopedMakeCurrent> scoped_make_current;
63 if (cleanup_cb_)
64 std::move(cleanup_cb_).Run(this);
65
66 // If the shared context is lost, |shared_context_state_| will be null.
67 if (!shared_context_state_) {
68 have_context = false;
69 } else {
70 if (!shared_context_state_->IsCurrent(nullptr)) {
71 scoped_make_current.emplace(shared_context_state_->context(),
72 shared_context_state_->surface());
73 have_context = scoped_make_current->IsContextCurrent();
74 }
75 shared_context_state_->RemoveContextLostObserver(this);
76 }
77 texture_->RemoveLightweightRef(have_context);
78 }
79
GetTextureBase() const80 TextureBase* AbstractTextureImplOnSharedContext::GetTextureBase() const {
81 return texture_;
82 }
83
SetParameteri(GLenum pname,GLint param)84 void AbstractTextureImplOnSharedContext::SetParameteri(GLenum pname,
85 GLint param) {
86 NOTIMPLEMENTED();
87 }
88
BindStreamTextureImage(gl::GLImage * image,GLuint service_id)89 void AbstractTextureImplOnSharedContext::BindStreamTextureImage(
90 gl::GLImage* image,
91 GLuint service_id) {
92 const GLint level = 0;
93 const GLuint target = texture_->target();
94 texture_->SetLevelStreamTextureImage(
95 target, level, image, Texture::ImageState::UNBOUND, service_id);
96 texture_->SetLevelCleared(target, level, true);
97 }
98
BindImage(gl::GLImage * image,bool client_managed)99 void AbstractTextureImplOnSharedContext::BindImage(gl::GLImage* image,
100 bool client_managed) {
101 NOTIMPLEMENTED();
102 }
103
GetImage() const104 gl::GLImage* AbstractTextureImplOnSharedContext::GetImage() const {
105 NOTIMPLEMENTED();
106 return nullptr;
107 }
108
SetCleared()109 void AbstractTextureImplOnSharedContext::SetCleared() {
110 NOTIMPLEMENTED();
111 }
112
SetCleanupCallback(CleanupCallback cb)113 void AbstractTextureImplOnSharedContext::SetCleanupCallback(
114 CleanupCallback cb) {
115 cleanup_cb_ = std::move(cb);
116 }
117
OnContextLost()118 void AbstractTextureImplOnSharedContext::OnContextLost() {
119 if (cleanup_cb_)
120 std::move(cleanup_cb_).Run(this);
121 shared_context_state_->RemoveContextLostObserver(this);
122 shared_context_state_.reset();
123 }
124
125 AbstractTextureImplOnSharedContextPassthrough::
AbstractTextureImplOnSharedContextPassthrough(GLenum target,scoped_refptr<gpu::SharedContextState> shared_context_state)126 AbstractTextureImplOnSharedContextPassthrough(
127 GLenum target,
128 scoped_refptr<gpu::SharedContextState> shared_context_state)
129 : shared_context_state_(std::move(shared_context_state)) {
130 DCHECK(shared_context_state_);
131
132 // The calling code which wants to create this abstract texture should have
133 // already made the shared context current.
134 DCHECK(shared_context_state_->IsCurrent(nullptr));
135
136 // Create a gles2 Texture.
137 GLuint service_id = 0;
138 auto* api = gl::g_current_gl_context;
139 api->glGenTexturesFn(1, &service_id);
140
141 GLint prev_texture = 0;
142 api->glGetIntegervFn(GetTextureBindingQuery(target), &prev_texture);
143
144 api->glBindTextureFn(target, service_id);
145 api->glTexParameteriFn(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
146 api->glTexParameteriFn(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
147 api->glTexParameteriFn(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
148 api->glTexParameteriFn(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
149
150 glBindTexture(target, prev_texture);
151
152 texture_ = new TexturePassthrough(service_id, target);
153 shared_context_state_->AddContextLostObserver(this);
154 }
155
156 AbstractTextureImplOnSharedContextPassthrough::
~AbstractTextureImplOnSharedContextPassthrough()157 ~AbstractTextureImplOnSharedContextPassthrough() {
158 base::Optional<ui::ScopedMakeCurrent> scoped_make_current;
159 if (cleanup_cb_)
160 std::move(cleanup_cb_).Run(this);
161
162 // If the shared context is lost, |shared_context_state_| will be null and the
163 // |texture_| is already marked to have lost its context.
164 if (shared_context_state_) {
165 // Make the |shared_context_state_|'s context current before destroying the
166 // |texture_| since
167 // destructor is not guaranteed to be called on the context on which the
168 // |texture_| was created.
169 if (!shared_context_state_->IsCurrent(nullptr)) {
170 scoped_make_current.emplace(shared_context_state_->context(),
171 shared_context_state_->surface());
172
173 // If |shared_context_state_|'s context is not current, then mark context
174 // lost for the |texture_|.
175 if (!scoped_make_current->IsContextCurrent())
176 texture_->MarkContextLost();
177 }
178 shared_context_state_->RemoveContextLostObserver(this);
179 }
180 texture_.reset();
181 }
182
GetTextureBase() const183 TextureBase* AbstractTextureImplOnSharedContextPassthrough::GetTextureBase()
184 const {
185 return texture_.get();
186 }
187
SetParameteri(GLenum pname,GLint param)188 void AbstractTextureImplOnSharedContextPassthrough::SetParameteri(GLenum pname,
189 GLint param) {
190 NOTIMPLEMENTED();
191 }
192
BindStreamTextureImage(gl::GLImage * image,GLuint service_id)193 void AbstractTextureImplOnSharedContextPassthrough::BindStreamTextureImage(
194 gl::GLImage* image,
195 GLuint service_id) {
196 NOTIMPLEMENTED();
197 }
198
BindImage(gl::GLImage * image,bool client_managed)199 void AbstractTextureImplOnSharedContextPassthrough::BindImage(
200 gl::GLImage* image,
201 bool client_managed) {
202 NOTIMPLEMENTED();
203 }
204
GetImage() const205 gl::GLImage* AbstractTextureImplOnSharedContextPassthrough::GetImage() const {
206 NOTIMPLEMENTED();
207 return nullptr;
208 }
209
SetCleared()210 void AbstractTextureImplOnSharedContextPassthrough::SetCleared() {
211 NOTIMPLEMENTED();
212 }
213
SetCleanupCallback(CleanupCallback cb)214 void AbstractTextureImplOnSharedContextPassthrough::SetCleanupCallback(
215 CleanupCallback cb) {
216 cleanup_cb_ = std::move(cb);
217 }
218
OnContextLost()219 void AbstractTextureImplOnSharedContextPassthrough::OnContextLost() {
220 if (cleanup_cb_)
221 std::move(cleanup_cb_).Run(this);
222 texture_->MarkContextLost();
223 shared_context_state_->RemoveContextLostObserver(this);
224 shared_context_state_ = nullptr;
225 }
226
227 } // namespace gles2
228 } // namespace gpu
229