OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 "ui/gl/gl_image_shm.h" | |
6 | |
7 #include "base/debug/trace_event.h" | |
8 #include "base/process/process_handle.h" | |
9 #include "ui/gl/scoped_binders.h" | |
10 | |
11 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | |
12 defined(USE_OZONE) | |
13 #include "ui/gl/gl_surface_egl.h" | |
14 #endif | |
15 | |
16 namespace gfx { | |
17 | |
18 namespace { | |
19 | |
20 bool ValidFormat(unsigned internalformat) { | |
21 switch (internalformat) { | |
22 case GL_BGRA8_EXT: | |
23 case GL_RGBA8_OES: | |
24 return true; | |
25 default: | |
26 return false; | |
27 } | |
28 } | |
29 | |
30 GLenum TextureFormat(unsigned internalformat) { | |
31 switch (internalformat) { | |
32 case GL_BGRA8_EXT: | |
33 return GL_BGRA_EXT; | |
34 case GL_RGBA8_OES: | |
35 return GL_RGBA; | |
36 default: | |
37 NOTREACHED(); | |
38 return 0; | |
39 } | |
40 } | |
41 | |
42 GLenum DataFormat(unsigned internalformat) { | |
43 return TextureFormat(internalformat); | |
44 } | |
45 | |
46 GLenum DataType(unsigned internalformat) { | |
47 switch (internalformat) { | |
48 case GL_BGRA8_EXT: | |
49 case GL_RGBA8_OES: | |
50 return GL_UNSIGNED_BYTE; | |
51 default: | |
52 NOTREACHED(); | |
53 return 0; | |
54 } | |
55 } | |
56 | |
57 GLenum BytesPerPixel(unsigned internalformat) { | |
58 switch (internalformat) { | |
59 case GL_BGRA8_EXT: | |
60 case GL_RGBA8_OES: | |
61 return 4; | |
62 default: | |
63 NOTREACHED(); | |
64 return 0; | |
65 } | |
66 } | |
67 | |
68 } // namespace | |
69 | |
70 GLImageShm::GLImageShm(gfx::Size size, unsigned internalformat) | |
71 : size_(size), | |
72 internalformat_(internalformat) | |
73 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | |
74 defined(USE_OZONE) | |
75 , | |
76 egl_texture_id_(0u), | |
77 egl_image_(EGL_NO_IMAGE_KHR) | |
78 #endif | |
79 { | |
80 } | |
81 | |
82 GLImageShm::~GLImageShm() { Destroy(); } | |
83 | |
84 bool GLImageShm::Initialize(gfx::GpuMemoryBufferHandle buffer) { | |
85 if (!ValidFormat(internalformat_)) { | |
86 DVLOG(0) << "Invalid format: " << internalformat_; | |
87 return false; | |
88 } | |
89 | |
90 if (!base::SharedMemory::IsHandleValid(buffer.handle)) | |
91 return false; | |
92 | |
93 base::SharedMemory shared_memory(buffer.handle, true); | |
94 | |
95 // Duplicate the handle. | |
96 base::SharedMemoryHandle duped_shared_memory_handle; | |
97 if (!shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), | |
98 &duped_shared_memory_handle)) { | |
99 DVLOG(0) << "Failed to duplicate shared memory handle."; | |
100 return false; | |
101 } | |
102 | |
103 shared_memory_.reset( | |
104 new base::SharedMemory(duped_shared_memory_handle, true)); | |
105 return true; | |
106 } | |
107 | |
108 void GLImageShm::Destroy() { | |
109 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | |
110 defined(USE_OZONE) | |
111 if (egl_image_ != EGL_NO_IMAGE_KHR) { | |
112 eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_); | |
113 egl_image_ = EGL_NO_IMAGE_KHR; | |
114 } | |
115 | |
116 if (egl_texture_id_) { | |
117 glDeleteTextures(1, &egl_texture_id_); | |
118 egl_texture_id_ = 0u; | |
119 } | |
120 #endif | |
121 } | |
122 | |
123 gfx::Size GLImageShm::GetSize() { return size_; } | |
124 | |
125 bool GLImageShm::BindTexImage(unsigned target) { | |
126 TRACE_EVENT0("gpu", "GLImageShm::BindTexImage"); | |
127 DCHECK(shared_memory_); | |
128 DCHECK(ValidFormat(internalformat_)); | |
129 | |
130 size_t size = size_.GetArea() * BytesPerPixel(internalformat_); | |
131 DCHECK(!shared_memory_->memory()); | |
132 if (!shared_memory_->Map(size)) { | |
133 DVLOG(0) << "Failed to map shared memory."; | |
134 return false; | |
135 } | |
136 | |
137 DCHECK(shared_memory_->memory()); | |
138 | |
139 #if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \ | |
140 defined(USE_OZONE) | |
141 if (target == GL_TEXTURE_EXTERNAL_OES) { | |
142 if (egl_image_ == EGL_NO_IMAGE_KHR) { | |
143 DCHECK_EQ(0u, egl_texture_id_); | |
144 glGenTextures(1, &egl_texture_id_); | |
145 | |
146 { | |
147 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); | |
148 | |
149 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
150 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
151 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
152 glTexImage2D(GL_TEXTURE_2D, | |
153 0, // mip level | |
154 TextureFormat(internalformat_), | |
155 size_.width(), | |
156 size_.height(), | |
157 0, // border | |
158 DataFormat(internalformat_), | |
159 DataType(internalformat_), | |
160 shared_memory_->memory()); | |
161 } | |
162 | |
163 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; | |
164 // Need to pass current EGL rendering context to eglCreateImageKHR for | |
165 // target type EGL_GL_TEXTURE_2D_KHR. | |
166 egl_image_ = | |
167 eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), | |
168 eglGetCurrentContext(), | |
169 EGL_GL_TEXTURE_2D_KHR, | |
170 reinterpret_cast<EGLClientBuffer>(egl_texture_id_), | |
171 attrs); | |
172 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_) | |
173 << "Error creating EGLImage: " << eglGetError(); | |
174 } else { | |
175 ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); | |
176 | |
177 glTexSubImage2D(GL_TEXTURE_2D, | |
178 0, // mip level | |
179 0, // x-offset | |
180 0, // y-offset | |
181 size_.width(), | |
182 size_.height(), | |
183 DataFormat(internalformat_), | |
184 DataType(internalformat_), | |
185 shared_memory_->memory()); | |
186 } | |
187 | |
188 glEGLImageTargetTexture2DOES(target, egl_image_); | |
189 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
190 | |
191 shared_memory_->Unmap(); | |
192 return true; | |
193 } | |
194 #endif | |
195 | |
196 DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target); | |
197 glTexImage2D(target, | |
198 0, // mip level | |
199 TextureFormat(internalformat_), | |
200 size_.width(), | |
201 size_.height(), | |
202 0, // border | |
203 DataFormat(internalformat_), | |
204 DataType(internalformat_), | |
205 shared_memory_->memory()); | |
206 | |
207 shared_memory_->Unmap(); | |
208 return true; | |
209 } | |
210 | |
211 } // namespace gfx | |
OLD | NEW |