summaryrefslogtreecommitdiff
path: root/chromium/gpu/command_buffer/service/passthrough_program_cache.cc
blob: ae8bb020502bcaa58a56eccde63de4a669bdfbeb (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
// Copyright (c) 2017 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/passthrough_program_cache.h"

#include <stddef.h>

#include "base/base64.h"
#include "ui/gl/gl_bindings.h"

#if defined(USE_EGL)
#include "ui/gl/angle_platform_impl.h"
#include "ui/gl/gl_surface_egl.h"
#endif  // defined(USE_EGL)

#ifndef EGL_ANGLE_program_cache_control
#define EGL_ANGLE_program_cache_control 1
#define EGL_PROGRAM_CACHE_SIZE_ANGLE 0x3455
#define EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE 0x3456
#define EGL_PROGRAM_CACHE_RESIZE_ANGLE 0x3457
#define EGL_PROGRAM_CACHE_TRIM_ANGLE 0x3458
#define EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE 0x3459
#endif /* EGL_ANGLE_program_cache_control */

namespace gpu {
namespace gles2 {

namespace {

bool ProgramCacheControlExtensionAvailable() {
#if defined(USE_EGL)
  // The display should be initialized if the extension is available.
  return gl::g_driver_egl.ext.b_EGL_ANGLE_program_cache_control;
#else
  return false;
#endif  // defined(USE_EGL)
}

}  // namespace

PassthroughProgramCache::PassthroughProgramCache(
    size_t max_cache_size_bytes,
    bool disable_gpu_shader_disk_cache)
    : disable_gpu_shader_disk_cache_(disable_gpu_shader_disk_cache) {
  if (!CacheEnabled()) {
    return;
  }

#if defined(USE_EGL)
  EGLDisplay display = gl::GLSurfaceEGL::GetHardwareDisplay();
  DCHECK(display != EGL_NO_DISPLAY);

  eglProgramCacheResizeANGLE(display, max_cache_size_bytes,
                             EGL_PROGRAM_CACHE_RESIZE_ANGLE);
#endif  // defined(USE_EGL)
}

PassthroughProgramCache::~PassthroughProgramCache() {
#if defined(USE_EGL)
  // Ensure the program cache callback is cleared.
  angle::ResetCacheProgramCallback();
#endif  // defined(USE_EGL)
}

void PassthroughProgramCache::ClearBackend() {
  Trim(0);
}

ProgramCache::ProgramLoadResult PassthroughProgramCache::LoadLinkedProgram(
    GLuint program,
    Shader* shader_a,
    Shader* shader_b,
    const LocationMap* bind_attrib_location_map,
    const std::vector<std::string>& transform_feedback_varyings,
    GLenum transform_feedback_buffer_mode,
    GLES2DecoderClient* client) {
  NOTREACHED();
  return PROGRAM_LOAD_FAILURE;
}

void PassthroughProgramCache::SaveLinkedProgram(
    GLuint program,
    const Shader* shader_a,
    const Shader* shader_b,
    const LocationMap* bind_attrib_location_map,
    const std::vector<std::string>& transform_feedback_varyings,
    GLenum transform_feedback_buffer_mode,
    GLES2DecoderClient* client) {
  NOTREACHED();
}

void PassthroughProgramCache::LoadProgram(const std::string& key,
                                          const std::string& program) {
  if (!CacheEnabled()) {
    // Early exit if this display can't support cache control
    return;
  }

#if defined(USE_EGL)
  EGLDisplay display = gl::GLSurfaceEGL::GetHardwareDisplay();
  DCHECK(display != EGL_NO_DISPLAY);

  std::string key_decoded;
  std::string program_decoded;
  base::Base64Decode(key, &key_decoded);
  base::Base64Decode(program, &program_decoded);

  eglProgramCachePopulateANGLE(display, key_decoded.c_str(), key_decoded.size(),
                               program_decoded.c_str(), program_decoded.size());
#endif  // defined(USE_EGL)
}

size_t PassthroughProgramCache::Trim(size_t limit) {
  if (!CacheEnabled()) {
    // Early exit if this display can't support cache control
    return 0;
  }

#if defined(USE_EGL)
  EGLDisplay display = gl::GLSurfaceEGL::GetHardwareDisplay();
  DCHECK(display != EGL_NO_DISPLAY);

  EGLint trimmed =
      eglProgramCacheResizeANGLE(display, limit, EGL_PROGRAM_CACHE_TRIM_ANGLE);
  return static_cast<size_t>(trimmed);
#else
  return 0;
#endif  // defined(USE_EGL)
}

bool PassthroughProgramCache::CacheEnabled() const {
  return ProgramCacheControlExtensionAvailable() &&
         !disable_gpu_shader_disk_cache_;
}

}  // namespace gles2
}  // namespace gpu