OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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 "chrome/gpu/gpu_backing_store_glx_context.h" | |
6 | |
7 #include "app/gfx/gl/gl_bindings.h" | |
8 #include "app/x11_util.h" | |
9 #include "base/scoped_ptr.h" | |
10 #include "chrome/gpu/gpu_thread.h" | |
11 | |
12 // Must be last. | |
13 #include <X11/Xutil.h> | |
14 | |
15 GpuBackingStoreGLXContext::GpuBackingStoreGLXContext(GpuThread* gpu_thread) | |
16 : gpu_thread_(gpu_thread), | |
17 tried_to_init_(false), | |
18 context_(NULL), | |
19 previous_window_id_(0), | |
20 frame_buffer_for_scrolling_(0), | |
21 is_frame_buffer_bound_(false), | |
22 temp_scroll_texture_id_(0) { | |
23 } | |
24 | |
25 GpuBackingStoreGLXContext::~GpuBackingStoreGLXContext() { | |
26 if (temp_scroll_texture_id_) { | |
27 glDeleteTextures(1, &temp_scroll_texture_id_); | |
28 temp_scroll_texture_id_ = 0; | |
29 } | |
30 | |
31 if (frame_buffer_for_scrolling_) | |
32 glDeleteFramebuffersEXT(1, &frame_buffer_for_scrolling_); | |
33 | |
34 if (context_) | |
35 glXDestroyContext(gpu_thread_->display(), context_); | |
36 } | |
37 | |
38 GLXContext GpuBackingStoreGLXContext::BindContext(XID window_id) { | |
39 DCHECK(!is_frame_buffer_bound_); | |
40 | |
41 if (tried_to_init_) { | |
42 if (!context_) | |
43 return NULL; | |
44 if (!previous_window_id_ || previous_window_id_ != window_id) { | |
45 bool success = glXMakeCurrent(gpu_thread_->display(), window_id, | |
46 context_); | |
47 DCHECK(success); | |
48 } | |
49 previous_window_id_ = window_id; | |
50 return context_; | |
51 } | |
52 tried_to_init_ = true; | |
53 | |
54 int attrib_list[] = { GLX_RGBA, GLX_DOUBLEBUFFER, 0 }; | |
55 scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info( | |
56 glXChooseVisual(gpu_thread_->display(), 0, attrib_list)); | |
57 if (!visual_info.get()) | |
58 return NULL; | |
59 | |
60 context_ = glXCreateContext(gpu_thread_->display(), visual_info.get(), | |
61 NULL, True); | |
62 bool success = glXMakeCurrent(gpu_thread_->display(), window_id, context_); | |
63 DCHECK(success); | |
64 return context_; | |
65 } | |
66 | |
67 bool GpuBackingStoreGLXContext::BindTextureForScrolling( | |
68 XID window_id, | |
69 const gfx::Size& size) { | |
70 DCHECK(!is_frame_buffer_bound_); | |
71 BindContext(window_id); | |
72 | |
73 // Create a new destination texture if the old one isn't properly sized. | |
74 // This means we try to re-use old ones without re-creating all the texture | |
75 // to save work in the common case of scrolling a window repeatedly that | |
76 // doesn't change size. | |
77 if (temp_scroll_texture_id_ == 0 || | |
78 size != temp_scroll_texture_size_) { | |
79 if (!temp_scroll_texture_id_) { | |
80 // There may be no temporary one created yet. | |
81 glGenTextures(1, &temp_scroll_texture_id_); | |
82 } | |
83 | |
84 // Create a new texture in the context with random garbage in it large | |
85 // enough to fit the required size. | |
86 glBindTexture(GL_TEXTURE_2D, temp_scroll_texture_id_); | |
87 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
88 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
89 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), | |
90 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); | |
91 glBindTexture(GL_TEXTURE_2D, 0); | |
92 } | |
93 | |
94 if (!frame_buffer_for_scrolling_) | |
95 glGenFramebuffersEXT(1, &frame_buffer_for_scrolling_); | |
96 glBindFramebufferEXT(GL_FRAMEBUFFER, frame_buffer_for_scrolling_); | |
97 is_frame_buffer_bound_ = true; | |
98 | |
99 // Release our color attachment. | |
100 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | |
101 temp_scroll_texture_id_, 0); | |
102 | |
103 DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == | |
104 GL_FRAMEBUFFER_COMPLETE_EXT); | |
105 return true; | |
106 } | |
107 | |
108 unsigned int GpuBackingStoreGLXContext::SwapTextureForScrolling( | |
109 unsigned int old_texture, | |
110 const gfx::Size& old_size) { | |
111 // Unbind the framebuffer, which we expect to be bound. | |
112 DCHECK(is_frame_buffer_bound_); | |
113 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); | |
114 is_frame_buffer_bound_ = false; | |
115 | |
116 DCHECK(temp_scroll_texture_id_); | |
117 unsigned int new_texture = temp_scroll_texture_id_; | |
118 | |
119 temp_scroll_texture_id_ = old_texture; | |
120 temp_scroll_texture_size_ = old_size; | |
121 | |
122 return new_texture; | |
123 } | |
OLD | NEW |