1 /*
   2  * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "config.h"
  27 
  28 #include <wtf/java/JavaEnv.h>
  29 #include "RenderingQueue.h"
  30 #include "RQRef.h"
  31 
  32 #include <wtf/java/JavaRef.h>
  33 #include <wtf/HashMap.h>
  34 #include <wtf/NeverDestroyed.h>
  35 
  36 #include "com_sun_webkit_graphics_WCRenderQueue.h"
  37 
  38 namespace WebCore {
  39 
  40 typedef HashMap<char*, RefPtr<ByteBuffer> > Addr2ByteBuffer;
  41 
  42 static Addr2ByteBuffer& getAddr2ByteBuffer()
  43 {
  44     static NeverDestroyed<Addr2ByteBuffer> container;
  45     return container.get();
  46 }
  47 
  48 /*static*/
  49 RefPtr<RenderingQueue> RenderingQueue::create(
  50     const JLObject &jRQ,
  51     int capacity,
  52     bool autoFlush)
  53 {
  54     return adoptRef(new RenderingQueue(
  55         jRQ,
  56         capacity,
  57         autoFlush));
  58 }
  59 
  60 RenderingQueue& RenderingQueue::freeSpace(int size) {
  61     if (m_buffer && !m_buffer->hasFreeSpace(size)) {
  62         flushBuffer();
  63         if (m_autoFlush) {
  64             flush();
  65         }
  66     }
  67     if (!m_buffer) {
  68         m_buffer = RefPtr<ByteBuffer>(ByteBuffer::create(std::max(m_capacity, size)));
  69     }
  70     return *this;
  71 }
  72 
  73 void RenderingQueue::flush() {
  74     JNIEnv* env = WebCore_GetJavaEnv();
  75 
  76     static jmethodID midFwkFlush = env->GetMethodID(
  77             PG_GetRenderQueueClass(env), "fwkFlush", "()V");
  78     ASSERT(midFwkFlush);
  79 
  80     env->CallVoidMethod(getWCRenderingQueue(), midFwkFlush);
  81     CheckAndClearException(env);
  82 }
  83 
  84 void RenderingQueue::disposeGraphics() {
  85     JNIEnv* env = WebCore_GetJavaEnv();
  86     // The method is called from the dtor which potentially can be called after VM detach.
  87     // So the check for nullptr.
  88     if (!env)
  89        return;
  90 
  91     static jmethodID midFwkDisposeGraphics = env->GetMethodID(
  92         PG_GetRenderQueueClass(env), "fwkDisposeGraphics", "()V");
  93     ASSERT(midFwkDisposeGraphics);
  94 
  95     env->CallVoidMethod(getWCRenderingQueue(), midFwkDisposeGraphics);
  96     CheckAndClearException(env);
  97 }
  98 
  99 /*
 100  * The method is called on Event thread (so, it's not concurrent with JS and the release of resources).
 101  */
 102 RenderingQueue& RenderingQueue::flushBuffer() {
 103     if (isEmpty()) {
 104         return *this;
 105     }
 106     JNIEnv* env = WebCore_GetJavaEnv();
 107 
 108     static jmethodID midFwkAddBuffer = env->GetMethodID(PG_GetRenderQueueClass(env),
 109         "fwkAddBuffer", "(Ljava/nio/ByteBuffer;)V");
 110     ASSERT(midFwkAddBuffer);
 111 
 112     Addr2ByteBuffer &a2bb = getAddr2ByteBuffer();
 113     a2bb.set(m_buffer->bufferAddress(), m_buffer);
 114     env->CallVoidMethod(
 115         getWCRenderingQueue(),
 116         midFwkAddBuffer,
 117         (jobject)(m_buffer->createDirectByteBuffer(env)));
 118     CheckAndClearException(env);
 119 
 120     m_buffer = nullptr;
 121 
 122     return *this;
 123 }
 124 }
 125 
 126 using namespace WebCore;
 127 
 128 extern "C" {
 129 
 130 JNIEXPORT void JNICALL Java_com_sun_webkit_graphics_WCRenderQueue_twkRelease
 131     (JNIEnv* env, jobject, jobjectArray bufs)
 132 {
 133     /*
 134      * This method should be called on the Event thread to synchronize with JavaScript
 135      * by thread. JavaScript may access resources kept in ByteBuffer::m_refList,
 136      * so when a resource is dereferenced (as a result of ByteBuffer destruction)
 137      * it should be thread safe.
 138      */
 139     Addr2ByteBuffer& a2bb = getAddr2ByteBuffer();
 140     for (int i = 0; i < env->GetArrayLength(bufs); ++i) {
 141         char *key = (char *)env->GetDirectBufferAddress(
 142             JLObject(env->GetObjectArrayElement(bufs, i)));
 143         if (key != 0) {
 144             a2bb.remove(key);
 145         }
 146     }
 147 }
 148 
 149 }