1 /*
   2  * Copyright (c) 2017, 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 package sun.java2d.xr;
  26 
  27 import java.nio.ByteBuffer;
  28 import java.util.HashMap;
  29 import java.util.LinkedList;
  30 
  31 /**
  32  * Manages the state of the buffers for uploading the AA tiles.
  33  * There is always only one non-Shared-memory buffer (can be re-used immediatly
  34  * once XPutImage is issued), and a vrious number of SHM buffers in case SHM
  35  * is supported on the system.
  36  *
  37  * @author Clemens Eisserer
  38  */
  39 public class AATileBufMan {
  40    
  41     private static int SHM_NUM_BUFFERS = 4;
  42     private final static int TILE_BUF_WIDTH = 256;
  43     private final static int TILE_BUF_HEIGHT = 256;
  44     
  45     ByteBuffer shmBuffer;
  46     int shmBufferScan;
  47     
  48     AATileBuffer nonShmTile;
  49     
  50     AATileBuffer activeTile;
  51     LinkedList<AATileBuffer> idleShmMasks;
  52     HashMap<Long, AATileBuffer> pendingShmMasks;
  53     AATileBuffer fenceQueuePendingTile;
  54     
  55     int shmCnt;
  56     int noShmCnt;
  57     
  58     int maskPicture;
  59     int maskPixmap;
  60     long maskGC;
  61     
  62     public AATileBufMan() {
  63         idleShmMasks = new LinkedList<>();
  64         pendingShmMasks = new HashMap<>();                        
  65 
  66         nonShmTile = new AATileBuffer(this, TILE_BUF_WIDTH, TILE_BUF_HEIGHT, TILE_BUF_WIDTH, 0, 0, ByteBuffer.allocateDirect(TILE_BUF_WIDTH * TILE_BUF_HEIGHT), false);
  67         
  68         String shmProp = System.getProperty("sun.java2d.xr.shm");
  69         
  70         if(shmProp == null || shmProp.length() > 0 
  71                 && Character.toLowerCase(shmProp.charAt(0)) == 'f') {
  72             if(System.getProperty("sun.java2d.shmBuffers") != null) {
  73                 SHM_NUM_BUFFERS = Integer.parseInt(System.getProperty("sun.java2d.shmBuffers"));
  74             }
  75 
  76             if((shmBuffer = initShmImage(TILE_BUF_WIDTH, TILE_BUF_HEIGHT * SHM_NUM_BUFFERS)) != null) {
  77                 for(int i = 0; i < SHM_NUM_BUFFERS; i++) {
  78                     int tileYOffset = TILE_BUF_HEIGHT * i;
  79                     
  80                     shmBuffer.position(tileYOffset * shmBufferScan);
  81                     ByteBuffer tileBuffer = shmBuffer.slice();
  82                     AATileBuffer aaShmBuf = new AATileBuffer(this, TILE_BUF_WIDTH, TILE_BUF_HEIGHT, shmBufferScan, tileYOffset, i + 1, tileBuffer, true);
  83                     idleShmMasks.add(aaShmBuf);
  84                 }
  85 
  86             }
  87 
  88             shmBuffer.position(0);
  89         }
  90     }
  91     
  92     public void initResources(XRBackendDeferred con, int parentXID) {
  93         maskPixmap = con.createPixmap(parentXID, 8, TILE_BUF_WIDTH, TILE_BUF_HEIGHT);
  94         maskPicture = con.createPicture(maskPixmap, XRUtils.PictStandardA8);
  95         maskGC = con.createGC(maskPixmap);
  96         con.setGCExposures(maskGC, false);
  97     }
  98     
  99    
 100     public AATileBuffer getActiveTileBuffer() {
 101         if(activeTile != null) {
 102             return activeTile;
 103         }
 104         
 105         if(idleShmMasks.size() > 0) {
 106             //System.out.println("shm tiles available: "+idleShmMasks.size());
 107             activeTile = idleShmMasks.removeLast();
 108             shmCnt++;
 109         } else {
 110             //System.out.println("shmtiles exhausted");
 111             activeTile = nonShmTile;
 112             noShmCnt++;
 113         }
 114         
 115         if(((shmCnt + noShmCnt) % 10000 == 0)) {
 116             System.out.println("Shm: "+shmCnt+" noShm:"+noShmCnt);
 117         }
 118         
 119         return activeTile;
 120     }
 121     
 122     public void pollPendingFences() {
 123         if(pendingShmMasks.size() > 0) {
 124             java.util.Iterator<Long> shmSeqIt = pendingShmMasks.keySet().iterator();
 125             
 126             while(shmSeqIt.hasNext()) {
 127                 long pendingSeq = shmSeqIt.next();
 128                 
 129                 if(pollForTileCompletion(pendingSeq)) {
 130               //      System.out.println("Pending fence received: " + pendingSeq);
 131                     AATileBuffer idleBuffer = pendingShmMasks.get(pendingSeq);
 132                 //    System.out.println("tile now available again: "+idleBuffer.getTileId());
 133                     idleShmMasks.add(idleBuffer);
 134                     
 135                     shmSeqIt.remove();
 136                 }                   
 137             }
 138         }
 139     }
 140     
 141     public void registerFenceSeqForActiveBuffer(long seq) {
 142         assert(fenceQueuePendingTile != null);
 143         pendingShmMasks.put(seq, fenceQueuePendingTile);
 144        // System.out.println("fence queued for tile: "+fenceQueuePendingTile.getTileId());
 145         fenceQueuePendingTile = null;
 146     }
 147     
 148     
 149     public void markActiveBufferFlushed(boolean shmQueued) {
 150         if(shmQueued) {
 151            // pendingShmMasks.push(activeTile);
 152            assert (fenceQueuePendingTile == null);
 153            fenceQueuePendingTile = activeTile;
 154         } else if(activeTile != nonShmTile) {
 155             idleShmMasks.add(activeTile);
 156         }
 157         
 158         activeTile.reset();        
 159         activeTile = null;
 160     }
 161     
 162     public int getIdleShmBufferCnt() {
 163         return idleShmMasks.size();
 164     }
 165 
 166     public boolean isFencePending() {
 167         return fenceQueuePendingTile != null;
 168     }
 169   
 170     public int getMaskPictureXid() {
 171         return maskPicture;
 172     }
 173     
 174     public long getMaskGCPtr() {
 175         return maskGC;
 176     }
 177     
 178     public int getMaskPixmapXid() {
 179         return maskPixmap;
 180     }
 181     
 182     private native ByteBuffer initShmImage(int width, int height);
 183     
 184     private native boolean pollForTileCompletion(long fenceSeq);
 185   
 186 }