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 }