summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service/gpu_processor_mac.cc
blob: 4d250ac7808f2a76c0409145a7dfe22252d1f201 (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
// Copyright (c) 2011 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/service/gpu_processor.h"
#include "ui/gfx/gl/gl_context.h"

using ::base::SharedMemory;

namespace gpu {

bool GPUProcessor::Initialize(
    gfx::PluginWindowHandle window,
    const gfx::Size& size,
    const gles2::DisallowedExtensions& disallowed_extensions,
    const char* allowed_extensions,
    const std::vector<int32>& attribs,
    GPUProcessor* parent,
    uint32 parent_texture_id) {
  // Get the parent decoder and the GLContext to share IDs with, if any.
  gles2::GLES2Decoder* parent_decoder = NULL;
  gfx::GLContext* parent_context = NULL;
  if (parent) {
    parent_decoder = parent->decoder_.get();
    DCHECK(parent_decoder);

    parent_context = parent_decoder->GetGLContext();
    DCHECK(parent_context);
  }

  scoped_ptr<gfx::GLContext> context(
      gfx::GLContext::CreateOffscreenGLContext(parent_context));
  if (!context.get())
    return false;

  // On Mac OS X since we can not render on-screen we don't even
  // attempt to create a view based GLContext. The only difference
  // between "on-screen" and "off-screen" rendering on this platform
  // is whether we allocate an AcceleratedSurface, which transmits the
  // rendering results back to the browser.
  if (window) {
    surface_.reset(new AcceleratedSurface());

    // Note that although the GLContext is passed to Initialize and the
    // GLContext will later be owned by the decoder, AcceleratedSurface does
    // not hold on to the reference. It simply extracts the underlying GL
    // context in order to share the namespace with another context.
    if (!surface_->Initialize(context.get(), false)) {
      LOG(ERROR) << "GPUProcessor::Initialize failed to "
                 << "initialize AcceleratedSurface.";
      Destroy();
      return false;
    }
  }

  return InitializeCommon(context.release(),
                          size,
                          disallowed_extensions,
                          allowed_extensions,
                          attribs,
                          parent_decoder,
                          parent_texture_id);
}

void GPUProcessor::Destroy() {
  if (surface_.get()) {
    surface_->Destroy();
    surface_.reset();
  }

  DestroyCommon();
}

uint64 GPUProcessor::SetWindowSizeForIOSurface(const gfx::Size& size) {
  // This is called from an IPC handler, so it's undefined which context is
  // current. Make sure the right one is.
  decoder_->GetGLContext()->MakeCurrent();

  ResizeOffscreenFrameBuffer(size);
  decoder_->UpdateOffscreenFrameBufferSize();

  // Note: The following line changes the current context again.
  return surface_->SetSurfaceSize(size);
}

TransportDIB::Handle GPUProcessor::SetWindowSizeForTransportDIB(
    const gfx::Size& size) {
  ResizeOffscreenFrameBuffer(size);
  decoder_->UpdateOffscreenFrameBufferSize();
  return surface_->SetTransportDIBSize(size);
}

void GPUProcessor::SetTransportDIBAllocAndFree(
      Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
      Callback1<TransportDIB::Id>::Type* deallocator) {
  surface_->SetTransportDIBAllocAndFree(allocator, deallocator);
}

uint64 GPUProcessor::GetSurfaceId() {
  if (!surface_.get())
    return 0;
  return surface_->GetSurfaceId();
}

uint64 GPUProcessor::swap_buffers_count() const {
  return swap_buffers_count_;
}

void GPUProcessor::set_acknowledged_swap_buffers_count(
    uint64 acknowledged_swap_buffers_count) {
  acknowledged_swap_buffers_count_ = acknowledged_swap_buffers_count;
}

void GPUProcessor::DidDestroySurface() {
  // When a browser window with a GPUProcessor is closed, the render process
  // will attempt to finish all GL commands, it will busy-wait on the GPU
  // process until the command queue is empty. If a paint is pending, the GPU
  // process won't process any GL commands until the browser sends a paint ack,
  // but since the browser window is already closed, it will never arrive.
  // To break this infinite loop, the browser tells the GPU process that the
  // surface became invalid, which causes the GPU process to not wait for paint
  // acks.
  surface_.reset();
}

void GPUProcessor::WillSwapBuffers() {
  DCHECK(decoder_.get());
  DCHECK(decoder_->GetGLContext());
  DCHECK(decoder_->GetGLContext()->IsCurrent());

  ++swap_buffers_count_;

  if (surface_.get()) {
    surface_->SwapBuffers();
  }

  if (wrapped_swap_buffers_callback_.get()) {
    wrapped_swap_buffers_callback_->Run();
  }
}

}  // namespace gpu