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