summaryrefslogtreecommitdiffstats
path: root/gpu/pgl/pgl.cc
blob: 6f24a31a4b54dc66bca7e7309a2a7a89a0c77312 (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// 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.

#include "gpu/command_buffer/client/gles2_cmd_helper.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/client/gles2_lib.h"
#include "gpu/pgl/command_buffer_pepper.h"
#include "gpu/pgl/pgl.h"

namespace {
const int32 kTransferBufferSize = 512 * 1024;

class PGLContextImpl {
 public:
  PGLContextImpl(NPP npp,
              NPDevice* device,
              NPDeviceContext3D* device_context);
  ~PGLContextImpl();

  // Initlaize a PGL context with a transfer buffer of a particular size.
  bool Initialize(int32 transfer_buffer_size);

  // Destroy all resources associated with the PGL context.
  void Destroy();

  // Make a PGL context current for the calling thread.
  static bool MakeCurrent(PGLContextImpl* pgl_context);

  // Display all content rendered since last call to SwapBuffers.
  bool SwapBuffers();

 private:
  PGLContextImpl(const PGLContextImpl&);
  void operator=(const PGLContextImpl&);

  NPP npp_;
  NPDevice* device_;
  NPDeviceContext3D* device_context_;
  CommandBufferPepper* command_buffer_;
  gpu::gles2::GLES2CmdHelper* gles2_helper_;
  int32 transfer_buffer_id_;
  gpu::gles2::GLES2Implementation* gles2_implementation_;
};

THREAD_LOCAL PGLContextImpl* g_current_pgl_context;

PGLContextImpl::PGLContextImpl(NPP npp,
                               NPDevice* device,
                               NPDeviceContext3D* device_context)
    : npp_(npp),
      device_(device),
      device_context_(device_context),
      command_buffer_(NULL),
      gles2_helper_(NULL),
      transfer_buffer_id_(0),
      gles2_implementation_(NULL) {
}

PGLContextImpl::~PGLContextImpl() {
  Destroy();
}

bool PGLContextImpl::Initialize(int32 transfer_buffer_size) {
  // Create and initialize the objects required to issue GLES2 calls.
  command_buffer_ = new CommandBufferPepper(
      npp_, device_, device_context_);
  gles2_helper_ = new gpu::gles2::GLES2CmdHelper(command_buffer_);
  if (gles2_helper_->Initialize()) {
    transfer_buffer_id_ =
        command_buffer_->CreateTransferBuffer(kTransferBufferSize);
    gpu::Buffer transfer_buffer =
        command_buffer_->GetTransferBuffer(transfer_buffer_id_);
    if (transfer_buffer.ptr) {
      gles2_implementation_ = new gpu::gles2::GLES2Implementation(
          gles2_helper_,
          transfer_buffer.size,
          transfer_buffer.ptr,
          transfer_buffer_id_);
      return true;
    }
  }

  // Tear everything down if initialization failed.
  Destroy();
  return false;
}

void PGLContextImpl::Destroy() {
  delete gles2_implementation_;
  gles2_implementation_ = NULL;

  if (command_buffer_ && transfer_buffer_id_ != 0) {
    command_buffer_->DestroyTransferBuffer(transfer_buffer_id_);
    transfer_buffer_id_ = 0;
  }

  delete gles2_helper_;
  gles2_helper_ = NULL;

  delete command_buffer_;
  command_buffer_ = NULL;
}

bool PGLContextImpl::MakeCurrent(PGLContextImpl* pgl_context) {
  g_current_pgl_context = pgl_context;
  if (pgl_context)
    gles2::SetGLContext(pgl_context->gles2_implementation_);
  else
    gles2::SetGLContext(NULL);

  return true;
}

bool PGLContextImpl::SwapBuffers() {
  gles2_implementation_->SwapBuffers();
  return true;
}
}  // namespace anonymous

extern "C" {

PGLContext pglCreateContext(NPP npp,
                            NPDevice* device,
                            NPDeviceContext3D* device_context) {
  PGLContextImpl* pgl_context = new PGLContextImpl(
      npp, device, device_context);
  if (pgl_context->Initialize(kTransferBufferSize)) {
    return pgl_context;
  }

  delete pgl_context;
  return NULL;
}

PGLBoolean pglMakeCurrent(PGLContext pgl_context) {
  return PGLContextImpl::MakeCurrent(static_cast<PGLContextImpl*>(pgl_context));
}

PGLContext pglGetCurrentContext(void) {
  return g_current_pgl_context;
}

PGLBoolean pglSwapBuffers(void) {
  if (!g_current_pgl_context)
    return false;

  return g_current_pgl_context->SwapBuffers();
}

PGLBoolean pglDestroyContext(PGLContext pgl_context) {
  if (!pgl_context)
    return false;

  delete pgl_context;
  return true;
}

}  // extern "C"