• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "test/linux/glx_renderer.h"
12 
13 #include <X11/Xlib.h>
14 #include <X11/Xutil.h>
15 #include <assert.h>
16 #include <stdlib.h>
17 
18 namespace webrtc {
19 namespace test {
20 
GlxRenderer(size_t width,size_t height)21 GlxRenderer::GlxRenderer(size_t width, size_t height)
22     : width_(width), height_(height), display_(NULL), context_(NULL) {
23   assert(width > 0);
24   assert(height > 0);
25 }
26 
~GlxRenderer()27 GlxRenderer::~GlxRenderer() {
28   Destroy();
29 }
30 
Init(const char * window_title)31 bool GlxRenderer::Init(const char* window_title) {
32   if ((display_ = XOpenDisplay(NULL)) == NULL) {
33     Destroy();
34     return false;
35   }
36 
37   int screen = DefaultScreen(display_);
38 
39   XVisualInfo* vi;
40   int attr_list[] = {
41       GLX_DOUBLEBUFFER, GLX_RGBA, GLX_RED_SIZE,   4,  GLX_GREEN_SIZE, 4,
42       GLX_BLUE_SIZE,    4,        GLX_DEPTH_SIZE, 16, None,
43   };
44 
45   if ((vi = glXChooseVisual(display_, screen, attr_list)) == NULL) {
46     Destroy();
47     return false;
48   }
49 
50   context_ = glXCreateContext(display_, vi, 0, true);
51   if (context_ == NULL) {
52     Destroy();
53     return false;
54   }
55 
56   XSetWindowAttributes window_attributes;
57   window_attributes.colormap = XCreateColormap(
58       display_, RootWindow(display_, vi->screen), vi->visual, AllocNone);
59   window_attributes.border_pixel = 0;
60   window_attributes.event_mask = StructureNotifyMask | ExposureMask;
61   window_ = XCreateWindow(display_, RootWindow(display_, vi->screen), 0, 0,
62                           width_, height_, 0, vi->depth, InputOutput,
63                           vi->visual, CWBorderPixel | CWColormap | CWEventMask,
64                           &window_attributes);
65   XFree(vi);
66 
67   XSetStandardProperties(display_, window_, window_title, window_title, None,
68                          NULL, 0, NULL);
69 
70   Atom wm_delete = XInternAtom(display_, "WM_DELETE_WINDOW", True);
71   if (wm_delete != None) {
72     XSetWMProtocols(display_, window_, &wm_delete, 1);
73   }
74 
75   XMapRaised(display_, window_);
76 
77   if (!glXMakeCurrent(display_, window_, context_)) {
78     Destroy();
79     return false;
80   }
81   GlRenderer::Init();
82   if (!glXMakeCurrent(display_, None, NULL)) {
83     Destroy();
84     return false;
85   }
86 
87   Resize(width_, height_);
88   return true;
89 }
90 
Destroy()91 void GlxRenderer::Destroy() {
92   if (context_ != NULL) {
93     glXMakeCurrent(display_, window_, context_);
94     GlRenderer::Destroy();
95     glXMakeCurrent(display_, None, NULL);
96     glXDestroyContext(display_, context_);
97     context_ = NULL;
98   }
99 
100   if (display_ != NULL) {
101     XCloseDisplay(display_);
102     display_ = NULL;
103   }
104 }
105 
Create(const char * window_title,size_t width,size_t height)106 GlxRenderer* GlxRenderer::Create(const char* window_title,
107                                  size_t width,
108                                  size_t height) {
109   GlxRenderer* glx_renderer = new GlxRenderer(width, height);
110   if (!glx_renderer->Init(window_title)) {
111     // TODO(pbos): Add GLX-failed warning here?
112     delete glx_renderer;
113     return NULL;
114   }
115   return glx_renderer;
116 }
117 
Resize(size_t width,size_t height)118 void GlxRenderer::Resize(size_t width, size_t height) {
119   width_ = width;
120   height_ = height;
121   if (!glXMakeCurrent(display_, window_, context_)) {
122     abort();
123   }
124   GlRenderer::ResizeViewport(width_, height_);
125   if (!glXMakeCurrent(display_, None, NULL)) {
126     abort();
127   }
128 
129   XSizeHints* size_hints = XAllocSizeHints();
130   if (size_hints == NULL) {
131     abort();
132   }
133   size_hints->flags = PAspect;
134   size_hints->min_aspect.x = size_hints->max_aspect.x = width_;
135   size_hints->min_aspect.y = size_hints->max_aspect.y = height_;
136   XSetWMNormalHints(display_, window_, size_hints);
137   XFree(size_hints);
138 
139   XWindowChanges wc;
140   wc.width = static_cast<int>(width);
141   wc.height = static_cast<int>(height);
142   XConfigureWindow(display_, window_, CWWidth | CWHeight, &wc);
143 }
144 
OnFrame(const webrtc::VideoFrame & frame)145 void GlxRenderer::OnFrame(const webrtc::VideoFrame& frame) {
146   if (static_cast<size_t>(frame.width()) != width_ ||
147       static_cast<size_t>(frame.height()) != height_) {
148     Resize(static_cast<size_t>(frame.width()),
149            static_cast<size_t>(frame.height()));
150   }
151 
152   XEvent event;
153   if (!glXMakeCurrent(display_, window_, context_)) {
154     abort();
155   }
156   while (XPending(display_)) {
157     XNextEvent(display_, &event);
158     switch (event.type) {
159       case ConfigureNotify:
160         GlRenderer::ResizeViewport(event.xconfigure.width,
161                                    event.xconfigure.height);
162         break;
163       default:
164         break;
165     }
166   }
167 
168   GlRenderer::OnFrame(frame);
169   glXSwapBuffers(display_, window_);
170 
171   if (!glXMakeCurrent(display_, None, NULL)) {
172     abort();
173   }
174 }
175 }  // namespace test
176 }  // namespace webrtc
177