summaryrefslogtreecommitdiffstats
path: root/app/surface/accelerated_surface_mac.h
blob: 3808dcd11cdf975c314ff935a267623ddad4fead (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef APP_SURFACE_ACCELERATED_SURFACE_MAC_H_
#define APP_SURFACE_ACCELERATED_SURFACE_MAC_H_

#include <CoreFoundation/CoreFoundation.h>
#include <OpenGL/OpenGL.h>

#include "app/surface/transport_dib.h"
#include "base/callback.h"
#include "base/scoped_cftyperef.h"
#include "base/scoped_ptr.h"
#include "gfx/rect.h"
#include "gfx/size.h"

namespace gfx {
class Rect;
}

// Encapsulates an accelerated GL surface that can be shared across processes
// on systems that support it (10.6 and above). For systems that do not, it
// uses a regular dib. There will either be a GL Context or a TransportDIB,
// never both.

class AcceleratedSurface {
 public:
  AcceleratedSurface();
  virtual ~AcceleratedSurface() { }

  // Set up internal buffers. Returns false upon failure.
  bool Initialize();
  // Tear down. Must be called before destructor to prevent leaks.
  void Destroy();

  // These methods are used only when there is a GL surface.

  // Sets the accelerated surface to the given size, creating a new one if
  // the height or width changes. Returns a unique id of the IOSurface to
  // which the surface is bound, or 0 if no changes were made or an error
  // occurred. MakeCurrent() will have been called on the new surface.
  uint64 SetSurfaceSize(const gfx::Size& size);

  // Sets the GL context to be the current one for drawing. Returns true if
  // it succeeded.
  bool MakeCurrent();
  // Clear the surface to all white. Assumes the caller has already called
  // MakeCurrent().
  void Clear(const gfx::Rect& rect);
  // Call after making changes to the surface which require a visual update.
  // Makes the rendering show up in other processes.
  void SwapBuffers();
  CGLContextObj context() { return gl_context_; }

  // These methods are only used when there is a transport DIB.

  // Sets the transport DIB to the given size, creating a new one if the
  // height or width changes. Returns a handle to the new DIB, or a default
  // handle if no changes were made.
  TransportDIB::Handle SetTransportDIBSize(const gfx::Size& size);
  // Sets the methods to use for allocating and freeing memory for the
  // transport DIB.
  void SetTransportDIBAllocAndFree(
      Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
      Callback1<TransportDIB::Id>::Type* deallocator);

  // Get the accelerated surface size.
  gfx::Size GetSize() const { return surface_size_; }

 private:
  // Helper function to generate names for the backing texture, render buffers
  // and FBO.  On return, the resulting buffer names can be attached to |fbo_|.
  // |target| is the target type for the color buffer.
  void AllocateRenderBuffers(GLenum target, const gfx::Size& size);

  // Helper function to attach the buffers previously allocated by a call to
  // AllocateRenderBuffers().  On return, |fbo_| can be used for
  // rendering.  |target| must be the same value as used in the call to
  // AllocateRenderBuffers().  Returns |true| if the resulting framebuffer
  // object is valid.
  bool SetupFrameBufferObject(GLenum target);

  CGLContextObj gl_context_;
  CGLPBufferObj pbuffer_;
  // Either |io_surface_| or |transport_dib_| is a valid pointer, but not both.
  // |io_surface_| is non-NULL if the IOSurface APIs are supported (Mac OS X
  // 10.6 and later).
  // TODO(dspringer,kbr): Should the GPU backing store be encapsulated in its
  // own class so all this implementation detail is hidden?
  scoped_cftyperef<CFTypeRef> io_surface_;
  // TODO(dspringer): If we end up keeping this TransportDIB mechanism, this
  // should really be a scoped_ptr_malloc<>, with a deallocate functor that
  // runs |dib_free_callback_|.  I was not able to figure out how to
  // make this work (or even compile).
  scoped_ptr<TransportDIB> transport_dib_;
  gfx::Size surface_size_;
  GLuint texture_;
  GLuint fbo_;
  GLuint depth_stencil_renderbuffer_;
  // For tracking whether the default framebuffer / renderbuffer or
  // ones created by the end user are currently bound
  // TODO(kbr): Need to property hook up and track the OpenGL state and hook
  // up the notion of the currently bound FBO.
  GLuint bound_fbo_;
  GLuint bound_renderbuffer_;
  // Allocate a TransportDIB in the renderer.
  scoped_ptr<Callback2<size_t, TransportDIB::Handle*>::Type>
      dib_alloc_callback_;
  scoped_ptr<Callback1<TransportDIB::Id>::Type> dib_free_callback_;
};

#endif  // APP_SURFACE_ACCELERATED_SURFACE_MAC_H_